Compare commits

...

326 Commits

Author SHA1 Message Date
filipefurtad0
7320fa3f09 Update all locales with the latest Transifex translations 2025-10-17 10:17:14 +01:00
Rachel Arnould
c4c266246c Merge pull request #13507 from rioug/tag-rules-remove-angular
[Variant Tags] Remove angular from tag rule admin page
2025-10-15 23:16:05 +02:00
Gaetan Craig-Riou
b4a64185dd Merge pull request #13576 from dacook/test-log-level
Add env var option for test log level
2025-10-15 13:40:23 +11:00
Gaetan Craig-Riou
a905acb56e Merge pull request #13601 from openfoodfoundation/dependabot/bundler/redis-5.4.1
Bump redis from 5.2.0 to 5.4.1
2025-10-15 13:22:37 +11:00
Ahmed Ejaz
067fa80d0f Merge pull request #13458 from rioug/docker-upgrade-postgres
Docker upgrade postgres
2025-10-15 02:24:16 +05:00
dependabot[bot]
980cc9c724 Bump redis from 5.2.0 to 5.4.1
Bumps [redis](https://github.com/redis/redis-rb) from 5.2.0 to 5.4.1.
- [Changelog](https://github.com/redis/redis-rb/blob/master/CHANGELOG.md)
- [Commits](https://github.com/redis/redis-rb/compare/v5.2.0...v5.4.1)

---
updated-dependencies:
- dependency-name: redis
  dependency-version: 5.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-14 09:01:55 +00:00
Maikel
49d345e608 Merge pull request #13597 from deivid-rodriguez/fix-rspec-warning
Fix RSpec warning when running `Reporting::ReportRenderer.render_as` unit spec
2025-10-14 14:02:42 +11:00
David Cook
12a6f9ac40 Merge pull request #13593 from openfoodfoundation/dependabot/bundler/flipper-1.3.6
Bump flipper from 1.3.0 to 1.3.6
2025-10-14 14:02:01 +11:00
Maikel
7d4efe75c3 Merge pull request #13596 from deivid-rodriguez/upgrade-caniuse-lite-to-fix-webpack-warnings
Update caniuse-lite to fix `bin/webpack-dev-server` warnings
2025-10-14 14:01:39 +11:00
Maikel
2cd41f3b8f Merge pull request #13595 from deivid-rodriguez/migrate-old-rspec-syntax
Use supported RSpec syntax
2025-10-14 13:52:40 +11:00
Maikel
436d919fc3 Merge pull request #13594 from deivid-rodriguez/typo
Fix typo in getting started guide
2025-10-14 13:51:43 +11:00
Maikel Linke
7a12e7426f Pass actors instead of AR associations to Flipper
Apparently they removed support for checking collections of actors.
2025-10-14 13:32:51 +11:00
David Cook
bd58969fb5 Reduce test logging by default
These logs are rarely checked, and can take up a lot of disk space.

I wanted to reduce the dev log level too, but then realised it also affects the dev server stdout. So now the other suggestions seem like a good idea.. (eg link development.log to /dev/null)

Oh well, this change will at least reduce one source of unnecessary disk usage in a default installation, so I think worth doing.
2025-10-14 12:30:36 +11:00
David Cook
0a385cc67c Use same variable name as prod, staging and test 2025-10-14 12:07:12 +11:00
David Cook
be5a630b9d [fixup] shorter variable name 2025-10-14 12:06:14 +11:00
David Rodríguez
98889365f1 Fix RSpec warning when running Reporting::ReportRenderer.render_as unit spec
Before:

```
$ bundle exec rspec -e ".render_as"

(...)

Run options: include {:full_description=>/\.render_as/}
WARNING: Using the `raise_error` matcher without providing a specific error or message risks false positives, since `raise_error` will match when Ruby raises a `NoMethodError`, `NameError` or `ArgumentError`, potentially allowing the expectation to pass without even executing the method you are intending to call. Actual error raised was #<ActionController::BadRequest: report_format should be in [:csv, :json, :html, :xlsx, :pdf]>. Instead consider providing a specific error class or message. This message can be suppressed by setting: `RSpec::Expectations.configuration.on_potential_false_positives = :nothing`. Called from /path/to/spec/lib/reports/report_renderer_spec.rb:34:in `block (3 levels) in <main>'.
.

Finished in 0.02544 seconds (files took 4.08 seconds to load)
1 example, 0 failures
```

After this patch:

```
$ bundle exec rspec -e ".render_as"

(...)

Run options: include {:full_description=>/\.render_as/}
.

Finished in 0.02488 seconds (files took 4.09 seconds to load)
1 example, 0 failures
```
2025-10-13 20:46:15 +02:00
David Rodríguez
9227660faf Update caniuse-lite to fix bin/webpack-dev-server warnings
This is the result of running:

$  npx update-browserslist-db@latest

And fixes warnings like

> Browserslist: caniuse-lite is outdated. Please run:
>   npx update-browserslist-db@latest
>   Why you should do it regularly: https://github.com/browserslist/update-db#readme

when running `bin/webpack-dev-server`.
2025-10-13 20:27:22 +02:00
David Rodríguez
bdafc1ff02 Use supported RSpec syntax
This spec was using a very old syntax no longer supported by RSpec. It's
not currently influencing specs result because the spec running into
the error is currently set as "pending". However, the spec is still run
and the error is still visible.

Fixing the syntax does not fix the spec, but lets it get a bit further.
2025-10-13 16:05:59 +02:00
David Rodríguez
9457b0505d Fix typo in getting started guide 2025-10-13 15:54:43 +02:00
dependabot[bot]
755116e713 Bump flipper from 1.3.0 to 1.3.6
Bumps [flipper](https://github.com/flippercloud/flipper) from 1.3.0 to 1.3.6.
- [Release notes](https://github.com/flippercloud/flipper/releases)
- [Changelog](https://github.com/flippercloud/flipper/blob/main/Changelog.md)
- [Commits](https://github.com/flippercloud/flipper/compare/v1.3.0...v1.3.6)

---
updated-dependencies:
- dependency-name: flipper
  dependency-version: 1.3.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-13 09:20:50 +00:00
David Cook
4852ee2c6e Merge pull request #13587 from mkllnk/json-response
Clean up request specs testing JSON
2025-10-13 14:24:26 +11:00
Maikel
9ba215316b Merge pull request #13513 from mkllnk/add-cqcm-staging-server
Add CQCM staging server to platforms to share data with
2025-10-13 13:42:12 +11:00
Maikel
084f7a8a47 Merge pull request #13590 from openfoodfoundation/dependabot/bundler/newrelic_rpm-9.22.0
Bump newrelic_rpm from 9.9.0 to 9.22.0
2025-10-13 10:05:50 +11:00
Gaetan Craig-Riou
7c60dfb75c Merge pull request #13591 from openfoodfoundation/dependabot/bundler/rack-2.2.20
Bump rack from 2.2.19 to 2.2.20
2025-10-13 09:55:05 +11:00
dependabot[bot]
e2410105ce Bump rack from 2.2.19 to 2.2.20
Bumps [rack](https://github.com/rack/rack) from 2.2.19 to 2.2.20.
- [Release notes](https://github.com/rack/rack/releases)
- [Changelog](https://github.com/rack/rack/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rack/rack/compare/v2.2.19...v2.2.20)

---
updated-dependencies:
- dependency-name: rack
  dependency-version: 2.2.20
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-10 18:59:10 +00:00
dependabot[bot]
8b0207f4b1 Bump newrelic_rpm from 9.9.0 to 9.22.0
Bumps [newrelic_rpm](https://github.com/newrelic/newrelic-ruby-agent) from 9.9.0 to 9.22.0.
- [Release notes](https://github.com/newrelic/newrelic-ruby-agent/releases)
- [Changelog](https://github.com/newrelic/newrelic-ruby-agent/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/newrelic/newrelic-ruby-agent/compare/9.9.0...9.22.0)

---
updated-dependencies:
- dependency-name: newrelic_rpm
  dependency-version: 9.22.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-10 09:02:15 +00:00
Maikel Linke
d3319cfd69 Replace global spec helpers with faster let 2025-10-10 16:44:50 +11:00
Maikel Linke
378b5e656e Use already parsed JSON in specs
Existing helpers provide indifferent access already.
2025-10-10 16:44:08 +11:00
Maikel Linke
b2da57b496 Publish supplier of catalog item 2025-10-10 16:18:22 +11:00
Maikel Linke
c6a34cfe34 Move catalog_item builder into the right module 2025-10-10 16:18:22 +11:00
Maikel Linke
591a279927 DRY controller 2025-10-10 16:18:22 +11:00
Maikel Linke
86774b3e4e Tell data proxy the enterprise to update 2025-10-10 16:18:22 +11:00
Maikel Linke
2761cee5e6 Publish coordinates of addresses 2025-10-10 16:18:22 +11:00
Maikel Linke
9460d17417 Publish DFC endpoints as JSON 2025-10-10 16:18:22 +11:00
Maikel Linke
404c07a590 Spec DFC endpoint configuration
It looks like puma finds the file only under `/.well-known/dfc` and not
`/.well-known/dfc/` with a slash in staging environment while it works
here in dev and test.

And in any case, just placing the file in `public/` doesn't produce the
right content type.
2025-10-10 16:18:22 +11:00
Maikel Linke
f2f0d954c6 Move source of truth of platforms into one place
The first test tokens had an inconsistent client_id and I had to
introduce multiple mappings to get the right config. But that has been
harmonised and we can put the config in one place.
2025-10-10 16:18:22 +11:00
Maikel Linke
1028d42e35 Update test token for new dev client id 2025-10-10 16:18:22 +11:00
Maikel Linke
91ad63d1ed Use test token as source of truth for validity 2025-10-10 16:18:22 +11:00
Maikel Linke
2780ae78f7 Add CQCM production servers 2025-10-10 16:18:21 +11:00
Maikel Linke
bf661159c6 Notify data proxy of permission changes 2025-10-10 16:18:21 +11:00
Maikel Linke
ad78ef14ef Automate replacement of generated image URLs in Swagger doc 2025-10-10 16:18:21 +11:00
Maikel Linke
c7efa43cdb Add well-known config for SiB directory proxy 2025-10-10 16:18:21 +11:00
Maikel Linke
df6e553661 Add SuppliedProducts index endpoint 2025-10-10 16:18:21 +11:00
Maikel Linke
4d59343f6c List enterprises on DFC API 2025-10-10 16:18:21 +11:00
Maikel Linke
44d29e98e0 Fix publishing all enterprises when listing catalog 2025-10-10 16:18:21 +11:00
Maikel Linke
06c27d6aaf Spec current publish of catalog of all enterprises 2025-10-10 16:18:21 +11:00
Maikel Linke
cb9edfaed8 Show DPM platforms enabled for user 2025-10-10 16:18:21 +11:00
Maikel Linke
51a3085452 Add CQCM staging server to platforms 2025-10-10 16:18:21 +11:00
Maikel
8ccceccd92 Merge pull request #13580 from openfoodfoundation/dependabot/bundler/digest-3.2.0
Bump digest from 3.1.1 to 3.2.0
2025-10-10 11:16:05 +11:00
Filipe
5e58f11006 Merge pull request #13474 from garethdavisrogers/add-report-name-and-details
Add report name and details
2025-10-09 12:42:22 +01:00
Ahmed Ejaz
5d8ecc5e5c Merge pull request #13584 from openfoodfoundation/fix/dependabot-pr-error
use pull_request_target to run action in context of the base repo rather than forked dependabot repo
2025-10-09 03:37:35 +05:00
Ahmed Ejaz
12e70d729a use pull_request_target to run action in context of the base repo rather than forked dependabot repo 2025-10-09 03:33:41 +05:00
Gareth Rogers
dc61580da1 Merge branch 'master' into add-report-name-and-details 2025-10-08 17:23:28 -04:00
Gareth
b956d6f21b Added test coverage, converted instance_double to double as we do not need the actual method 2025-10-08 17:17:04 -04:00
dependabot[bot]
b5e3681eab Bump digest from 3.1.1 to 3.2.0
Bumps [digest](https://github.com/ruby/digest) from 3.1.1 to 3.2.0.
- [Release notes](https://github.com/ruby/digest/releases)
- [Commits](https://github.com/ruby/digest/compare/v3.1.1...v3.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-08 09:02:21 +00:00
Maikel
c45ac93a12 Merge pull request #13575 from mkllnk/hanging-specs
Deactivate Puffing Billy to avoid hanging specs
2025-10-08 16:54:18 +11:00
David Cook
60ee33053d Apply suggestions from code review 2025-10-08 14:15:56 +11:00
David Cook
a4ea311439 Add env var option for test log level
The test log level is already debug by default, but perhaps you don't want that because it results in a very large file over time, which isn't automatically cleaned up.

In that case, why not change the default, maybe to :info?
2025-10-08 14:02:05 +11:00
Maikel Linke
5b383237ea Deactivate Puffing Billy to avoid hanging specs 2025-10-08 13:26:37 +11:00
Maikel
de8029f877 Merge pull request #13564 from mkllnk/config-log
Make log-level configurable in staging
2025-10-08 13:24:56 +11:00
Gaetan Craig-Riou
d818162a9f Merge pull request #13568 from openfoodfoundation/dependabot/bundler/undercover-0.8.1
Bump undercover from 0.7.4 to 0.8.1
2025-10-08 09:56:22 +11:00
Gaetan Craig-Riou
9bd4d29027 Merge pull request #13567 from openfoodfoundation/dependabot/bundler/mime-types-3.7.0
Bump mime-types from 3.5.2 to 3.7.0
2025-10-08 09:51:59 +11:00
Gaetan Craig-Riou
742d442929 Merge pull request #13566 from openfoodfoundation/dependabot/bundler/rails-i18n-7.0.10
Bump rails-i18n from 7.0.9 to 7.0.10
2025-10-08 09:45:04 +11:00
Gaetan Craig-Riou
f08f744077 Merge pull request #13565 from openfoodfoundation/dependabot/npm_and_yarn/jasmine-core-5.12.0
Bump jasmine-core from 5.11.0 to 5.12.0
2025-10-08 09:44:05 +11:00
Gaetan Craig-Riou
72ab0ba3f5 Merge pull request #13573 from openfoodfoundation/dependabot/bundler/rack-2.2.19
Bump rack from 2.2.18 to 2.2.19
2025-10-08 09:39:42 +11:00
dependabot[bot]
bb4b483469 Bump rack from 2.2.18 to 2.2.19
Bumps [rack](https://github.com/rack/rack) from 2.2.18 to 2.2.19.
- [Release notes](https://github.com/rack/rack/releases)
- [Changelog](https://github.com/rack/rack/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rack/rack/compare/v2.2.18...v2.2.19)

---
updated-dependencies:
- dependency-name: rack
  dependency-version: 2.2.19
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-07 19:44:09 +00:00
Gareth Rogers
585073a326 Merge branch 'master' into add-report-name-and-details 2025-10-07 11:02:56 -04:00
Gareth
c3189892af Removed other rows for now. Can be added in future PRs 2025-10-07 11:01:55 -04:00
Gareth
417011909c Removed other filter rows. They weren't working and maybe not even relevant. The idea was to include order cycles and distributor ids as well, but it wasn't really requested so I'm taking it out. 2025-10-07 11:01:55 -04:00
Gareth
9ed612410f Changed default checking behavior of metadata controller 2025-10-07 11:01:55 -04:00
David Cook
7098cf2224 Merge pull request #13570 from openfoodfoundation/task/13521-move-dependabot-to-code-review
Remove project write permissions from Dependabot PR workflow
2025-10-07 10:12:55 +11:00
Ahmed Ejaz
4713e9046c Remove project write permissions from Dependabot PR workflow 2025-10-07 03:57:11 +05:00
David Cook
037030cf60 Merge pull request #13548 from mkllnk/test_rake
Configure rake specs in one place
2025-10-07 09:31:02 +11:00
dependabot[bot]
286f05d05c Bump undercover from 0.7.4 to 0.8.1
Bumps [undercover](https://github.com/grodowski/undercover) from 0.7.4 to 0.8.1.
- [Release notes](https://github.com/grodowski/undercover/releases)
- [Changelog](https://github.com/grodowski/undercover/blob/master/CHANGELOG.md)
- [Commits](https://github.com/grodowski/undercover/compare/v0.7.4...v0.8.1)

---
updated-dependencies:
- dependency-name: undercover
  dependency-version: 0.8.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-06 09:06:51 +00:00
dependabot[bot]
e9a750ce6d Bump mime-types from 3.5.2 to 3.7.0
Bumps [mime-types](https://github.com/mime-types/ruby-mime-types) from 3.5.2 to 3.7.0.
- [Changelog](https://github.com/mime-types/ruby-mime-types/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mime-types/ruby-mime-types/compare/v3.5.2...v3.7.0)

---
updated-dependencies:
- dependency-name: mime-types
  dependency-version: 3.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-06 09:06:17 +00:00
dependabot[bot]
8942f3c72b Bump rails-i18n from 7.0.9 to 7.0.10
Bumps [rails-i18n](https://github.com/svenfuchs/rails-i18n) from 7.0.9 to 7.0.10.
- [Changelog](https://github.com/svenfuchs/rails-i18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/svenfuchs/rails-i18n/compare/v7.0.9...v7.0.10)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-06 09:05:35 +00:00
dependabot[bot]
23b2c8e11b Bump jasmine-core from 5.11.0 to 5.12.0
Bumps [jasmine-core](https://github.com/jasmine/jasmine) from 5.11.0 to 5.12.0.
- [Release notes](https://github.com/jasmine/jasmine/releases)
- [Changelog](https://github.com/jasmine/jasmine/blob/main/RELEASE.md)
- [Commits](https://github.com/jasmine/jasmine/compare/v5.11.0...v5.12.0)

---
updated-dependencies:
- dependency-name: jasmine-core
  dependency-version: 5.12.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-06 09:05:06 +00:00
Gaetan Craig-Riou
9a9e9763cc Merge pull request #13546 from openfoodfoundation/task/13521-move-dependabot-to-code-review
Automate Dependabot PRs to Code Review column via GitHub Action
2025-10-06 16:21:14 +11:00
Maikel Linke
90cd2e0ba2 Make log-level configurable in staging
The new comment and code come from the Rails 8.0 default files.
2025-10-06 15:20:25 +11:00
Maikel
8c02bde7f2 Merge pull request #13472 from openfoodfoundation/dependabot/bundler/rswag-ui-2.16.0
Bump rswag-ui from 2.13.0 to 2.16.0
2025-10-06 15:14:58 +11:00
dependabot[bot]
8c1e0bae92 Bump rswag-ui from 2.13.0 to 2.16.0
Bumps [rswag-ui](https://github.com/rswag/rswag) from 2.13.0 to 2.16.0.
- [Release notes](https://github.com/rswag/rswag/releases)
- [Changelog](https://github.com/rswag/rswag/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rswag/rswag/compare/2.13.0...2.16.0)

---
updated-dependencies:
- dependency-name: rswag-ui
  dependency-version: 2.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-06 03:54:07 +00:00
Maikel
09c7288b11 Merge pull request #13471 from openfoodfoundation/dependabot/bundler/rspec-rails-7.1.1
Bump rspec-rails from 6.1.2 to 7.1.1
2025-10-06 14:51:22 +11:00
dependabot[bot]
d27ffe5fca Bump rspec-rails from 6.1.2 to 7.1.1
Bumps [rspec-rails](https://github.com/rspec/rspec-rails) from 6.1.2 to 7.1.1.
- [Changelog](https://github.com/rspec/rspec-rails/blob/main/Changelog.md)
- [Commits](https://github.com/rspec/rspec-rails/compare/v6.1.2...v7.1.1)

---
updated-dependencies:
- dependency-name: rspec-rails
  dependency-version: 7.1.1
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-06 02:34:38 +00:00
David Cook
6c94650e51 Merge pull request #13516 from mkllnk/lock-sprockets
Lock sprockets dependency to major version 3
2025-10-06 12:05:10 +11:00
Ahmed Ejaz
79bb469332 Update all locales with the latest Transifex translations 2025-10-06 03:54:40 +05:00
Ahmed Ejaz
2c4df63879 Add permissions for contents, pull-requests, and project in workflow 2025-10-06 03:35:57 +05:00
Ahmed Ejaz
9f5d73184f Add .secrets file to define GitHub secrets values locally 2025-10-04 19:24:07 +05:00
Ahmed Ejaz
4a5938c0f7 Add installation retrieval mode and payload for Dependabot token generation 2025-10-04 18:50:47 +05:00
Gareth Rogers
f414e04dea Merge branch 'master' into add-report-name-and-details 2025-10-01 09:54:51 -04:00
Filipe
ef4d3ec138 Merge pull request #13506 from chahmedejaz/task/13505-remove-stripe-redirect-monkey-patch
Remove Stripe redirect monkeypatch and ensure reliable checkout flow
2025-10-01 13:03:58 +01:00
Gareth Rogers
0a9eb173ea Add report name and details to CSV files 2025-10-01 13:59:43 +10:00
Gaetan Craig-Riou
f5a9ec7fa9 Merge pull request #13551 from openfoodfoundation/dependabot/npm_and_yarn/jasmine-core-5.11.0
Bump jasmine-core from 5.10.0 to 5.11.0
2025-10-01 09:29:17 +10:00
filipefurtad0
e190b87f12 Update all locales with the latest Transifex translations 2025-09-29 15:54:51 +01:00
Filipe
ff2e0f4d45 Merge pull request #13533 from chahmedejaz/task/13435-sort-products-by-on-hand-amount
Sort product list by 'on hand' amount
2025-09-29 15:07:00 +01:00
dependabot[bot]
d50bcbb70a Bump jasmine-core from 5.10.0 to 5.11.0
Bumps [jasmine-core](https://github.com/jasmine/jasmine) from 5.10.0 to 5.11.0.
- [Release notes](https://github.com/jasmine/jasmine/releases)
- [Changelog](https://github.com/jasmine/jasmine/blob/main/RELEASE.md)
- [Commits](https://github.com/jasmine/jasmine/compare/v5.10.0...v5.11.0)

---
updated-dependencies:
- dependency-name: jasmine-core
  dependency-version: 5.11.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-29 10:21:25 +00:00
Ahmed Ejaz
782f813a15 Add Dependabot PR test event and update workflow for token generation 2025-09-29 11:35:48 +05:00
Gaetan Craig-Riou
9b0545c33f Merge pull request #13550 from openfoodfoundation/dependabot/bundler/rack-2.2.18
Bump rack from 2.2.14 to 2.2.18
2025-09-29 09:39:35 +10:00
Gaetan Craig-Riou
55f162ff4a Create tag when tag input lose focus
This reflect the current behaviour of the angular tag input.
Plus fix spec helper.
2025-09-29 09:36:19 +10:00
Gaetan Craig-Riou
ede7650fc9 Replace space by -, to match angular tag functionality 2025-09-29 09:36:12 +10:00
dependabot[bot]
7631fd422e Bump rack from 2.2.14 to 2.2.18
Bumps [rack](https://github.com/rack/rack) from 2.2.14 to 2.2.18.
- [Release notes](https://github.com/rack/rack/releases)
- [Changelog](https://github.com/rack/rack/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rack/rack/compare/v2.2.14...v2.2.18)

---
updated-dependencies:
- dependency-name: rack
  dependency-version: 2.2.18
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-25 17:32:06 +00:00
Gaetan Craig-Riou
c2c2a9503c Rename stimulus controller based on the new shorter naming 2025-09-24 10:47:59 +10:00
Gaetan Craig-Riou
bc1823e276 Add http error handling
Because we are using fetch here to manually request turbo stream we have
to handle errors ourselves.
2025-09-24 10:46:37 +10:00
Gaetan Craig-Riou
01d5830480 Move turbo http error handling to its own file 2025-09-24 10:46:37 +10:00
Gaetan Craig-Riou
bad7369e67 Per review, fix tag rule filter spec 2025-09-24 10:46:37 +10:00
Gaetan Craig-Riou
ab65b2d745 Per review, fix various syntax/misspell 2025-09-24 10:46:37 +10:00
Gaetan Craig-Riou
f38aa73434 Per review, remove test class
It's better to use an anonymous class, and it also prevent the test
class from leaking the global namespace
2025-09-24 10:46:37 +10:00
Gaetan Craig-Riou
3862e0206c Limit to only one tag per tag rule 2025-09-24 10:46:34 +10:00
Gaetan Craig-Riou
3a0722f39c Remove tag related methods 2025-09-24 10:40:43 +10:00
Gaetan Craig-Riou
42f7f2606b Remove reordering testing
This functionality has been removed
2025-09-24 10:40:43 +10:00
Gaetan Craig-Riou
9d9f7e8717 Remove Angularjs files related to tag rules 2025-09-24 10:40:43 +10:00
Gaetan Craig-Riou
0cf244b211 Document variant filtering rule behavior
Add test to conver scenario where we have conficting rules
2025-09-24 10:40:43 +10:00
Gaetan Craig-Riou
646ba18b8a Fix bug, load tag rule types when update errors 2025-09-24 10:40:43 +10:00
Gaetan Craig-Riou
8bd631fbb7 Clean up tag rule form component template
Consolidate everything in one template and move visibility options to
the component.
2025-09-24 10:40:43 +10:00
Gaetan Craig-Riou
5c3acf38d7 Clean up stimulus usage
Use value and parameter when possible instead of relying on hidden
input
2025-09-24 10:40:43 +10:00
Gaetan Craig-Riou
afdc40d230 Move helper function to component
It's only used in the component so there is no need to keep it as an
helper.
2025-09-24 10:40:43 +10:00
Gaetan Craig-Riou
771573af1c Fix system spec to work with refactored screen 2025-09-24 10:40:43 +10:00
Gaetan Craig-Riou
953122b6f6 Fix adding new rule
We separate the default tag rules and the various tag rule groups by an
index of 1000. This is so the previous group does not overlap with the
current group. Rails will managed the non continusly numbered
tag_rule_attributes param just fine. It saves us from having to manage
the numbering of tag_rule_attributes in javascript
2025-09-24 10:40:43 +10:00
Gaetan Craig-Riou
75325e2935 Consolidate modal to add rule into a component 2025-09-24 10:40:43 +10:00
Gaetan Craig-Riou
7e48007d09 Add new tag group and add rule to tag group 2025-09-24 10:40:43 +10:00
Gaetan Craig-Riou
50ab0a494c Move tag rule group form to a component 2025-09-24 10:40:43 +10:00
Gaetan Craig-Riou
d3ef744daf Display existing grouped tag rules 2025-09-24 10:40:43 +10:00
Gaetan Craig-Riou
ccdd12bf59 Small improvment
- add value for preferred customer tags
- allow passing html options to preferred customer tags hidden field
2025-09-24 10:40:43 +10:00
Gaetan Craig-Riou
b66b033999 Small improvement
- allow passing html options to the hidden field with the tags values,
  to be used to add stimulus directive
- dispatch an input event when the hidden field with tags value gets
  updated, it allows stimulus controller (or javascript) to react to
  update
2025-09-24 10:40:34 +10:00
Gaetan Craig-Riou
35d37639af Refactor tag rule filter input
Consolidated four partials into one
2025-09-24 10:38:53 +10:00
Gaetan Craig-Riou
6790cad089 Add deleting tag rule
TagRuleController is now a subclass of Spree::Admin::BaseController
because Admin::ResourceController did not play well with turbo_stream.
And to be honest we did not need all the functionality provided by the
ResourceController
2025-09-24 10:38:53 +10:00
Gaetan Craig-Riou
7087d1b290 Add default tag rule
I tried to leverage turbo as much as possible
2025-09-24 10:38:53 +10:00
Gaetan Craig-Riou
8f0cdf8722 Move individual tag rule form to a component 2025-09-24 10:38:53 +10:00
Gaetan Craig-Riou
25f6db09a5 TagListInputComponent removed dependency on the form
This allows us to use the component in a context where there is no form
object defined.
2025-09-24 10:38:47 +10:00
Gaetan Craig-Riou
11006c3a60 Display default rule 2025-09-24 10:36:21 +10:00
Gaetan Craig-Riou
b2a3715a8b Fix bug
Don't add a leading coma when the tag list is empty
2025-09-24 10:36:21 +10:00
Gaetan Craig-Riou
693789d526 Merge pull request #13549 from openfoodfoundation/dependabot/npm_and_yarn/leaflet-geosearch-4.2.2
Bump leaflet-geosearch from 4.2.1 to 4.2.2
2025-09-24 09:49:41 +10:00
dependabot[bot]
d26b407801 Bump leaflet-geosearch from 4.2.1 to 4.2.2
Bumps [leaflet-geosearch](https://github.com/smeijer/leaflet-geosearch) from 4.2.1 to 4.2.2.
- [Release notes](https://github.com/smeijer/leaflet-geosearch/releases)
- [Commits](https://github.com/smeijer/leaflet-geosearch/compare/v4.2.1...v4.2.2)

---
updated-dependencies:
- dependency-name: leaflet-geosearch
  dependency-version: 4.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-22 09:12:58 +00:00
Maikel Linke
6d284023fe Configure rake specs in one place
So we don't have to add it to every rake spec file.
2025-09-22 17:27:58 +10:00
Maikel Linke
570b72868b Simplify task loading code 2025-09-22 17:27:58 +10:00
Maikel Linke
286d9f8e7d Remove unneeded declaration of Rails environment task in specs 2025-09-22 17:27:58 +10:00
Ahmed Ejaz
b0c3265cdb update migration test to assert nil cvv_response_message for ineligible payments 2025-09-22 11:57:38 +05:00
Ahmed Ejaz
6bb709e85e update test description to reflect patching of redirect_auth_url in cvv_result 2025-09-22 11:57:37 +05:00
filipefurtad0
fe257162b7 Update all locales with the latest Transifex translations 2025-09-22 07:56:21 +01:00
Ahmed Ejaz
b510736a8d refactor migration to use SpreePayment model instead of Spree::Payment 2025-09-22 11:55:43 +05:00
Ahmed Ejaz
2df0078ea9 fix lint issues 2025-09-22 11:55:43 +05:00
Ahmed Ejaz
ca079e6e26 add migration to migrate cvv_message_response value to redirect_auth_url
- As per the patch, cvv_message_response contains 3D verification URL for those payments which require it. So need to migrate to the new column to maintain data integrity
2025-09-22 11:55:43 +05:00
Ahmed Ejaz
ac06126f59 replace cvv_response_message usage with redirect_auth_url 2025-09-22 11:55:43 +05:00
Ahmed Ejaz
aecb5f49c9 fix spec as per current response we get for cvv_result 2025-09-22 11:54:20 +05:00
Ahmed Ejaz
a18fd54916 Simplify redirect logic in PaymentsController 2025-09-22 11:54:20 +05:00
Ahmed Ejaz
626b802ea7 add redirect_auth_url column and replace cvv_response_message for redirection
- Added redirect_auth_url column to spree_payments table
- Updated payment redirection logic to use redirect_auth_url instead of cvv_response_message
- Cleans up old monkeypatch usage and improves Stripe checkout reliability
2025-09-22 11:54:20 +05:00
Ahmed Ejaz
28ab41c47f Potential fix for code scanning alert no. 253: Workflow does not contain permissions
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2025-09-18 03:17:22 +05:00
Ahmed Ejaz
17a85e9c1c Update GitHub Actions workflow to use specific Dependabot token and set organization name explicitly 2025-09-18 03:01:44 +05:00
Maikel
9e746d1b40 Merge pull request #13531 from rioug/better-stimulus-name-for-component
Load component stimulus controller with a shorter name
2025-09-17 17:10:37 +10:00
Filipe
273f78b214 Merge pull request #13530 from mkllnk/hub-address-feature
Remove retired hub_address feature
2025-09-16 17:23:42 +01:00
Filipe
bd1d9892a2 Merge pull request #13487 from rioug/security-241-fix-url-sanitization
Fix url sanitization for Stripe authorisation URL
2025-09-16 16:40:11 +01:00
David Cook
cb825df75b Merge pull request #13536 from openfoodfoundation/dependabot/npm_and_yarn/leaflet-geosearch-4.2.1
Bump leaflet-geosearch from 4.2.0 to 4.2.1
2025-09-16 15:32:29 +10:00
Filipe
bfcadfd7c0 Merge pull request #13404 from cyrillefr/UnsavedChangesMustAppearOnRemovingSingleTagFromOrderCycle
Fixes Save button does not enable when removing only tag in OC
2025-09-15 13:27:26 +01:00
dependabot[bot]
255b5f1cd5 Bump leaflet-geosearch from 4.2.0 to 4.2.1
Bumps [leaflet-geosearch](https://github.com/smeijer/leaflet-geosearch) from 4.2.0 to 4.2.1.
- [Release notes](https://github.com/smeijer/leaflet-geosearch/releases)
- [Commits](https://github.com/smeijer/leaflet-geosearch/compare/v4.2.0...v4.2.1)

---
updated-dependencies:
- dependency-name: leaflet-geosearch
  dependency-version: 4.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-15 09:27:26 +00:00
Ahmed Ejaz
dffcd446fd Simplify backorderable priority SQL query in product sorting concern 2025-09-15 12:03:04 +05:00
Ahmed Ejaz
1987f0b667 Remove redundant SQL string checks in product sorting specs for clarity 2025-09-15 11:57:33 +05:00
Ahmed Ejaz
0b5efae8c4 Refactor sorting expectations in product_sort_by_stocks_spec for clarity and accuracy 2025-09-15 11:56:07 +05:00
Gaetan Craig-Riou
36bb7cb317 Fix vertical ellipsis menu compoenent spec 2025-09-15 10:46:16 +10:00
Ahmed Ejaz
49dbe1d039 Refactor comments for clarity in product sorting concerns 2025-09-15 02:15:03 +05:00
Ahmed Ejaz
c326aa6b23 Add comprehensive specs for sorting functionality 2025-09-15 01:59:40 +05:00
Ahmed Ejaz
ec91d717c7 Fix default sorting for 'on_hand' column to 'name asc' in admin products table 2025-09-13 01:31:38 +05:00
Ahmed Ejaz
da843d1ba1 Add sorting by stock levels using ransacker and update locale for 'on_hand' header 2025-09-13 01:11:21 +05:00
filipefurtad0
2c4b3ab8fc Update all locales with the latest Transifex translations 2025-09-12 08:41:29 +01:00
Gaetan Craig-Riou
1c7fbd1d2d Rename vertical ellipsis menu component files
There is no need to have a different name scheme to shorten stimulus
controller name. It's now inline with the other components
2025-09-10 15:27:56 +10:00
Gaetan Craig-Riou
8042dac74f Fix stimulus controller name to use the shorter version 2025-09-10 15:10:10 +10:00
Gaetan Craig-Riou
ad1ce00223 Generate a better stimulus name for component controller
Using the helper `definitionsFromContext` generate quite long name for
stimulus controller in component, ie :
`tag-list-input-component--tag-list-input`.
This custom loader will generate much more readable name, ie L
`tag-list-input`. It's expecting the following pattern :
ofn_component/ofn_controller.js and will fall back to the default
of replacing "_" by "- and "/" by "--" for controller not matching
the pattern.
2025-09-10 15:03:31 +10:00
Maikel Linke
d916ed2c96 Remove retired hub_address feature 2025-09-10 09:59:47 +10:00
Filipe
da66a2947c Merge pull request #13502 from cillian/replace-darker-background-disable-dynamically-inline-alert-page-alert-directives
Replace darker-background, disable-dynamically, inline-alert and page-alert Angular directives
2025-09-08 16:28:51 +01:00
David Cook
646d3b8ed9 Merge pull request #13524 from mkllnk/cleanup
Code cleanup
2025-09-08 14:31:34 +10:00
Gaetan Craig-Riou
1f15f094ce Per review, check the URL is from a stripe subdomain 2025-09-08 11:00:11 +10:00
filipefurtad0
adddee2c3c Update all locales with the latest Transifex translations 2025-09-05 09:52:44 +01:00
Cillian O'Ruanaidh
74e7bd5172 Update spec/system/consumer/shopping/cart_spec.rb test to use new disabled selector 2025-09-05 09:38:20 +01:00
Cillian O'Ruanaidh
66859f44ca Include LinkHelper which includes new :link_to_or_disable method to fix spec/views/spree/orders/edit.html.haml_spec.rb test 2025-09-05 09:38:20 +01:00
Cillian O'Ruanaidh
6f7a547e15 Add a :link_to_or_disabled helper method 2025-09-05 09:38:20 +01:00
Cillian O'Ruanaidh
c057c72321 Replace ofn-page-alert angular directive 2025-09-05 09:38:20 +01:00
Cillian O'Ruanaidh
7a3b4d394b Replace inline-alert angular directive 2025-09-05 09:38:20 +01:00
Cillian O'Ruanaidh
32e3fc0175 Replace disable-dynamically angular directive 2025-09-05 09:38:20 +01:00
Cillian O'Ruanaidh
23c9410a25 Replace darker-background angular directive 2025-09-05 09:38:20 +01:00
Maikel
7e9c5ea58b Merge pull request #13523 from filipefurtad0/content_spec_html
Adds coverage to homepage alert HTML content
2025-09-05 14:35:07 +10:00
Maikel Linke
6c313a1b5a Remove duplicate include of TimeHelpers in specs 2025-09-05 14:30:46 +10:00
Maikel Linke
244a88a1cd Removed unused user from report classes
We needed them for a feature toggle that doesn't exist anymore.
2025-09-05 14:29:01 +10:00
filipefurtad0
589315780c Adds coverage to homepage alert HTML content 2025-09-04 19:07:29 +01:00
Ahmed Ejaz
1654bb2b0a Rename job from 'move-pr-to-project' to 'move-pr-to-code-review' for clarity 2025-09-04 05:57:40 +05:00
Ahmed Ejaz
9f396a40b7 Update condition to move Dependabot PRs to Code Review for bump titles 2025-09-04 05:53:48 +05:00
Ahmed Ejaz
4bf1b7ac08 Add workflow to automatically move Dependabot PRs to Code Review 2025-09-04 05:53:28 +05:00
Gaetan Craig-Riou
2910082584 Merge pull request #13517 from openfoodfoundation/dependabot/npm_and_yarn/jasmine-core-5.10.0
Bump jasmine-core from 5.9.0 to 5.10.0
2025-09-03 16:54:57 +10:00
dependabot[bot]
70b5fda632 Bump jasmine-core from 5.9.0 to 5.10.0
Bumps [jasmine-core](https://github.com/jasmine/jasmine) from 5.9.0 to 5.10.0.
- [Release notes](https://github.com/jasmine/jasmine/releases)
- [Changelog](https://github.com/jasmine/jasmine/blob/main/RELEASE.md)
- [Commits](https://github.com/jasmine/jasmine/compare/v5.9.0...v5.10.0)

---
updated-dependencies:
- dependency-name: jasmine-core
  dependency-version: 5.10.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-01 18:05:10 +00:00
Maikel Linke
8bc82685ae Bump sprockets from 3.7.2 to 3.7.5
Changelog: https://github.com/rails/sprockets/blob/3.x/CHANGELOG.md
2025-09-01 16:56:22 +10:00
Maikel Linke
63125705ac Lock version of sprockets 2025-09-01 16:54:44 +10:00
Maikel Linke
9bf2dad343 Update all locales with the latest Transifex translations 2025-08-29 15:15:19 +10:00
David Cook
05b3417f77 Merge pull request #13512 from mkllnk/remove-timecop-usage
Remove remaining Timecop usage
2025-08-29 14:09:50 +10:00
Maikel Linke
403aa6ac6f Remove remaining Timecop usage 2025-08-29 11:16:20 +10:00
Filipe
fbad3ee9f4 Merge pull request #13484 from cesarlr/patch-1
Update Gemfile.lock
2025-08-28 19:38:59 +01:00
Filipe
ddb8b2d08f Merge pull request #13496 from dacook/fix-link
Fix link to enterprise payment methods tab
2025-08-28 19:17:37 +01:00
Filipe
42c9ee033a Merge pull request #13503 from AndreyUsyaev/usandy/fix-i18n-sells-options
Fix missed I18n translations for enterprises sells options
2025-08-28 18:50:07 +01:00
Maikel Linke
524634b4ea Bump wkhtmltopdf-binary from 0.12.6.9 to 0.12.6.10 to support Debian 13 2025-08-28 11:46:21 +01:00
César López Ramírez
0b97171bb0 Update Gemfile.lock
Upgrade wkhtmltopdf-binary to support Ubuntu 24.04
2025-08-28 11:46:21 +01:00
Filipe
b0c7e29b0d Merge pull request #13468 from mkllnk/rails-config-updates
Add Rails 7.0 and 7.1 framework defaults
2025-08-28 11:44:44 +01:00
Andrey Usyaev
3d7799df19 Fix code review remarks 2025-08-27 13:21:44 +03:00
Andrey Usyaev
5f02d88a86 Fix missed I18n translations for enterprises sells options 2025-08-27 13:21:44 +03:00
Maikel
bdae8e6478 Merge pull request #13475 from mkllnk/dfc-sib-tokens
Accept tokens from Startin'Blox OIDC server
2025-08-27 14:55:30 +10:00
Gaetan Craig-Riou
053ef05baf Merge pull request #13480 from mkllnk/time-travel
Replace Timecop with Rails' time helpers
2025-08-27 09:34:58 +10:00
Ahmed Ejaz
7fcb31d563 Update all locales with the latest Transifex translations 2025-08-25 11:49:44 +05:00
Gaetan Craig-Riou
31a7374808 Merge pull request #13444 from garethdavisrogers/fix-docker-dependency-and-db-dev-env
Added cmake dep to dockerfile and added script for db:schema:load tha…
2025-08-25 14:10:10 +10:00
Gareth
e5ce06ae39 Updated branch 2025-08-22 12:49:24 -04:00
Gareth Rogers
5f64204d51 Merge branch 'master' into fix-docker-dependency-and-db-dev-env 2025-08-22 08:31:27 -04:00
Maikel Linke
94b75540e4 Replace Timecop with Rails' time helpers
Rails 4.1 added time helpers but we never bothered using them. But now
I'm getting rid of the Timecop dependency and use standard helpers.

Beware though that the new helpers always freeze time. When you travel
to a certain date then the clock stops ticking while Timecop maintained
the passing of time.

The freezing of time could cause problems if you are trying to enforce a
timeout. But all current specs don't seem affected.

In most cases, the freezing will make it easier to avoid flaky specs.
2025-08-22 16:57:04 +10:00
Maikel Linke
6e489d7770 Enforce required DFC permissions 2025-08-22 16:46:59 +10:00
Maikel Linke
81b1169e77 Configure undercover to exclude files 2025-08-22 16:13:20 +10:00
Maikel
4b558b4820 Merge pull request #13501 from openfoodfoundation/dependabot/npm_and_yarn/sha.js-2.4.12
Bump sha.js from 2.4.11 to 2.4.12
2025-08-22 16:12:26 +10:00
Maikel
e224b8f63b Merge pull request #13500 from openfoodfoundation/dependabot/npm_and_yarn/cipher-base-1.0.6
Bump cipher-base from 1.0.4 to 1.0.6
2025-08-22 16:11:30 +10:00
Maikel
80bb0606b4 Merge pull request #13499 from openfoodfoundation/dependabot/npm_and_yarn/floating-ui/dom-1.7.4
Bump @floating-ui/dom from 1.7.3 to 1.7.4
2025-08-22 15:50:47 +10:00
dependabot[bot]
499fcc791e Bump sha.js from 2.4.11 to 2.4.12
Bumps [sha.js](https://github.com/crypto-browserify/sha.js) from 2.4.11 to 2.4.12.
- [Changelog](https://github.com/browserify/sha.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crypto-browserify/sha.js/compare/v2.4.11...v2.4.12)

---
updated-dependencies:
- dependency-name: sha.js
  dependency-version: 2.4.12
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-21 15:48:41 +00:00
dependabot[bot]
30dae3c3ea Bump cipher-base from 1.0.4 to 1.0.6
Bumps [cipher-base](https://github.com/crypto-browserify/cipher-base) from 1.0.4 to 1.0.6.
- [Changelog](https://github.com/browserify/cipher-base/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crypto-browserify/cipher-base/compare/v1.0.4...v1.0.6)

---
updated-dependencies:
- dependency-name: cipher-base
  dependency-version: 1.0.6
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-21 15:23:41 +00:00
dependabot[bot]
af247c32a3 Bump @floating-ui/dom from 1.7.3 to 1.7.4
Bumps [@floating-ui/dom](https://github.com/floating-ui/floating-ui/tree/HEAD/packages/dom) from 1.7.3 to 1.7.4.
- [Release notes](https://github.com/floating-ui/floating-ui/releases)
- [Changelog](https://github.com/floating-ui/floating-ui/blob/master/packages/dom/CHANGELOG.md)
- [Commits](https://github.com/floating-ui/floating-ui/commits/@floating-ui/dom@1.7.4/packages/dom)

---
updated-dependencies:
- dependency-name: "@floating-ui/dom"
  dependency-version: 1.7.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-21 09:48:24 +00:00
Gareth
6f9dcf7e27 remove bundle check 2025-08-20 11:04:40 -04:00
Gareth
2d064bab64 Created a bundler service that runs once removing responsibilities from any other services. The bundler service always runs install which should still be pretty fast if nothing or only a few gems have changed. A healthcheck won't work unless bundler runs continuously which is impractical. Instead, a checksum is generated on bundle install and sentinels in the other services have a definite confirmation that bundle is complete. The nice thing about this approach is that web, webpack, and sidekiq (which share the same bundles dependencies) will not concurrently run bundle install solving dep install redundancies. 2025-08-20 10:13:20 -04:00
Gareth
b69eb9bdff Specified BUNDLE_PATH AND BUNDLE_APP_CONFIG in Dockerfile 2025-08-20 08:48:21 -04:00
David Cook
f79c1879bd Test that you can actually get to Stripe to connect your account
Well.. almost.
2025-08-20 13:06:59 +10:00
David Cook
646d538a3d Fix broken link
This link would go to the enterprise edit screen, but didn't successfully select the payment methods panel.

Ideally, the spec would try to follow the link and verify that you can see the Connect with Stripe button. But it opens the link in a new tab and I'm not sure how to test that.
2025-08-20 11:54:47 +10:00
David Cook
90288b8cbf Merge pull request #13492 from chahmedejaz/revert/dependabot/bundler/rexml-3.3.9
500 Error preventing check out with Stripe payment method
2025-08-19 10:50:09 +10:00
Ahmed Ejaz
c821b0a285 revert "Bump rexml from 3.2.9 to 3.3.9" 2025-08-19 05:27:58 +05:00
Gareth
b95d798a27 Fixed webpack service so that web relies on its bundles. This has re-enabled JS 2025-08-18 12:24:27 -04:00
Gareth
e1e4aeac1f Added conditions to sidekiq too as it races db as well. Everything seems functional now 2025-08-18 11:52:52 -04:00
Gareth
c7ae47053e Added health check to avoid docker container racing 2025-08-18 11:38:57 -04:00
Gareth Rogers
5892ae1800 Merge branch 'master' into fix-docker-dependency-and-db-dev-env 2025-08-18 09:32:21 -04:00
Gaetan Craig-Riou
c37376d67e Merge pull request #13485 from openfoodfoundation/dependabot/bundler/bullet-8.0.8
Bump bullet from 7.1.6 to 8.0.8
2025-08-18 13:58:39 +10:00
Gaetan Craig-Riou
d3a2c09f66 Upgrade to postgres 16
Postgres 16 is shipped with Ubuntu 24 which is the version we will be
moving to in production
2025-08-18 10:45:54 +10:00
Gaetan Craig-Riou
d596e692d8 Upgrade postgres to version 14
This is the version currently availablein Ubuntu 22
2025-08-18 10:45:24 +10:00
Gaetan Craig-Riou
2df95dcbab No need to expose the postgres port
There is no need to expose the port to the host, all container will be
running in the same network, so they will have access to database port.
2025-08-18 10:45:18 +10:00
Ahmed Ejaz
7aa9b164e6 Add scope for ordering products by stock levels and update admin table header for on_hand sorting 2025-08-17 07:16:46 +05:00
Gareth
74368f939b By creating the db in the container on composition, the first migration file rejects the schema of the empty database. All I had to do was remove db creation from docker so that db:prepare will default to creating open_food_network_dev from schema.rb rather than perceiving a mismatch from the precreated docker db 2025-08-15 14:23:13 -04:00
Gareth
cb02cd39fe Reverting unexpected change to schema.rb as requested 2025-08-15 12:27:10 -04:00
dependabot[bot]
49ec5b2089 Bump bullet from 7.1.6 to 8.0.8
Bumps [bullet](https://github.com/flyerhzm/bullet) from 7.1.6 to 8.0.8.
- [Changelog](https://github.com/flyerhzm/bullet/blob/main/CHANGELOG.md)
- [Commits](https://github.com/flyerhzm/bullet/compare/7.1.6...8.0.8)

---
updated-dependencies:
- dependency-name: bullet
  dependency-version: 8.0.8
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-15 09:56:17 +00:00
Maikel
92ef5fe3d5 Merge pull request #13483 from openfoodfoundation/dependabot/bundler/pdf-reader-2.15.0
Bump pdf-reader from 2.12.0 to 2.15.0
2025-08-15 10:29:09 +10:00
Filipe
ae477b7e52 Merge pull request #13455 from kirst-n/13366-only-load-necessary-flatpickr
Optimise loading of language-specific date pickers
2025-08-14 23:24:59 +01:00
Filipe
0e191e5fca Merge pull request #13459 from rioug/13454-fix-redeemeing-voucher-when-using-paypal
[VINE] Redeem voucher before redirecting to payment url
2025-08-14 16:30:22 +01:00
dependabot[bot]
64f9ea6fc0 Bump pdf-reader from 2.12.0 to 2.15.0
Bumps [pdf-reader](https://github.com/yob/pdf-reader) from 2.12.0 to 2.15.0.
- [Changelog](https://github.com/yob/pdf-reader/blob/main/CHANGELOG)
- [Commits](https://github.com/yob/pdf-reader/compare/v2.12.0...v2.15.0)

---
updated-dependencies:
- dependency-name: pdf-reader
  dependency-version: 2.15.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-14 10:01:32 +00:00
Maikel
058c6749da Merge pull request #13477 from openfoodfoundation/dependabot/bundler/timecop-0.9.10
Bump timecop from 0.9.8 to 0.9.10
2025-08-14 13:20:18 +10:00
Maikel
2d15ec4458 Merge pull request #13478 from openfoodfoundation/dependabot/bundler/activerecord-7.1.5.2
Bump activerecord from 7.1.5.1 to 7.1.5.2
2025-08-14 13:18:58 +10:00
dependabot[bot]
56eaa8bb98 Bump activerecord from 7.1.5.1 to 7.1.5.2
Bumps [activerecord](https://github.com/rails/rails) from 7.1.5.1 to 7.1.5.2.
- [Release notes](https://github.com/rails/rails/releases)
- [Changelog](https://github.com/rails/rails/blob/v8.0.2.1/activerecord/CHANGELOG.md)
- [Commits](https://github.com/rails/rails/compare/v7.1.5.1...v7.1.5.2)

---
updated-dependencies:
- dependency-name: activerecord
  dependency-version: 7.1.5.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-14 01:21:32 +00:00
Gaetan Craig-Riou
118e18a78e Tighten url validation
Per recommendation from https://github.com/openfoodfoundation/openfoodnetwork/security/code-scanning/241
2025-08-13 22:27:42 +10:00
Gaetan Craig-Riou
cbced144d5 Clean up styling 2025-08-13 22:21:35 +10:00
dependabot[bot]
1e1f1e1e1b Bump timecop from 0.9.8 to 0.9.10
Bumps [timecop](https://github.com/travisjeffery/timecop) from 0.9.8 to 0.9.10.
- [Changelog](https://github.com/travisjeffery/timecop/blob/master/History.md)
- [Commits](https://github.com/travisjeffery/timecop/compare/v0.9.8...v0.9.10)

---
updated-dependencies:
- dependency-name: timecop
  dependency-version: 0.9.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-13 09:58:01 +00:00
Maikel Linke
1d2115766a Show product groups to platform user
I removed the caching of `managed_enterprises` in Permissions because
it's just a scope and calling it again is very cheap. And that makes the
method a lot easier to read now that we have a conditional here.

Accessing the managed enterprises via the user instead of a separate
scope on the Enterprise model also reduce the SQL queries. We may want
to use this method in more places. I prefer to keep the
admin-conditional in a permissions class instead of in the model.
2025-08-13 15:06:31 +10:00
Maikel Linke
6814ef43f4 Show addresses to platform users 2025-08-13 15:06:25 +10:00
Maikel Linke
c9e8294561 DRY with shared context 2025-08-13 15:02:09 +10:00
Maikel Linke
82d0e1bf68 Show enterprise to authorised platform user 2025-08-13 15:02:09 +10:00
Maikel Linke
b16e541a81 Show DFC catalog to authorised platform 2025-08-13 15:02:09 +10:00
Maikel Linke
c12d494de3 Demonstrate authentication as DFC client app 2025-08-13 15:02:09 +10:00
Maikel Linke
9be27842e1 Accepts tokens from Startin'Blox OIDC server
The API controllers don't know the new type of user yet and will raise
errors but we can work on that bit by bit.
2025-08-13 15:02:09 +10:00
Maikel Linke
2a7754edbf Add test for current token validation 2025-08-13 15:02:09 +10:00
Maikel Linke
cfeafbfc51 Update API docs with latest version 2025-08-13 15:02:08 +10:00
Maikel
1f8a9f9c76 Merge pull request #13470 from openfoodfoundation/dependabot/bundler/rack-2.2.14
Bump rack from 2.2.11 to 2.2.14
2025-08-13 12:45:59 +10:00
Maikel
b1893942ac Merge pull request #13469 from openfoodfoundation/dependabot/bundler/net-imap-0.4.20
Bump net-imap from 0.4.10 to 0.4.20
2025-08-13 12:40:50 +10:00
dependabot[bot]
ad59ed4d40 Bump rack from 2.2.11 to 2.2.14
Bumps [rack](https://github.com/rack/rack) from 2.2.11 to 2.2.14.
- [Release notes](https://github.com/rack/rack/releases)
- [Changelog](https://github.com/rack/rack/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rack/rack/compare/v2.2.11...v2.2.14)

---
updated-dependencies:
- dependency-name: rack
  dependency-version: 2.2.14
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-13 00:02:14 +00:00
Maikel
8491a167ed Merge pull request #13350 from mkllnk/dfc-ui
Add permission module with example data
2025-08-13 10:00:53 +10:00
Maikel Linke
05b00f16ad Move config option to a better place 2025-08-12 20:24:16 +10:00
Maikel Linke
78fdaa68c8 Update config files with Rails 7.1 templates 2025-08-12 20:24:16 +10:00
dependabot[bot]
59277292fb Bump net-imap from 0.4.10 to 0.4.20
Bumps [net-imap](https://github.com/ruby/net-imap) from 0.4.10 to 0.4.20.
- [Release notes](https://github.com/ruby/net-imap/releases)
- [Commits](https://github.com/ruby/net-imap/compare/v0.4.10...v0.4.20)

---
updated-dependencies:
- dependency-name: net-imap
  dependency-version: 0.4.20
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-12 06:54:11 +00:00
Maikel Linke
e8813833fa Add Rails 7.1 framework defaults template 2025-08-12 15:43:45 +10:00
Gaetan Craig-Riou
354a7ab687 Merge pull request #13465 from openfoodfoundation/dependabot/bundler/fugit-1.11.1
Bump fugit from 1.8.1 to 1.11.1
2025-08-12 15:06:20 +10:00
Gaetan Craig-Riou
a5a1ee9bd9 Merge pull request #13462 from openfoodfoundation/dependabot/bundler/thor-1.4.0
Bump thor from 1.3.1 to 1.4.0
2025-08-12 15:02:23 +10:00
Gaetan Craig-Riou
ad3f78ef69 Merge pull request #13466 from openfoodfoundation/dependabot/bundler/uri-0.13.2
Bump uri from 0.13.0 to 0.13.2
2025-08-12 14:58:40 +10:00
Gaetan Craig-Riou
e02497b163 Merge pull request #13467 from openfoodfoundation/dependabot/bundler/rails-html-sanitizer-1.6.1
Bump rails-html-sanitizer from 1.6.0 to 1.6.1
2025-08-12 14:57:59 +10:00
Gaetan Craig-Riou
7d2d94398f Merge pull request #13464 from openfoodfoundation/dependabot/bundler/cgi-0.3.7
Bump cgi from 0.3.6 to 0.3.7
2025-08-12 14:49:47 +10:00
Gaetan Craig-Riou
0ecf004ff2 Merge pull request #13463 from openfoodfoundation/dependabot/bundler/rexml-3.3.9
Bump rexml from 3.2.9 to 3.3.9
2025-08-12 14:48:06 +10:00
dependabot[bot]
444f448207 Bump rails-html-sanitizer from 1.6.0 to 1.6.1
Bumps [rails-html-sanitizer](https://github.com/rails/rails-html-sanitizer) from 1.6.0 to 1.6.1.
- [Release notes](https://github.com/rails/rails-html-sanitizer/releases)
- [Changelog](https://github.com/rails/rails-html-sanitizer/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rails/rails-html-sanitizer/compare/v1.6.0...v1.6.1)

---
updated-dependencies:
- dependency-name: rails-html-sanitizer
  dependency-version: 1.6.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-12 04:31:53 +00:00
dependabot[bot]
d9381b23d7 Bump uri from 0.13.0 to 0.13.2
Bumps [uri](https://github.com/ruby/uri) from 0.13.0 to 0.13.2.
- [Release notes](https://github.com/ruby/uri/releases)
- [Commits](https://github.com/ruby/uri/compare/v0.13.0...v0.13.2)

---
updated-dependencies:
- dependency-name: uri
  dependency-version: 0.13.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-12 04:31:50 +00:00
dependabot[bot]
6a9a2884d6 Bump fugit from 1.8.1 to 1.11.1
Bumps [fugit](https://github.com/floraison/fugit) from 1.8.1 to 1.11.1.
- [Changelog](https://github.com/floraison/fugit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/floraison/fugit/compare/v1.8.1...v1.11.1)

---
updated-dependencies:
- dependency-name: fugit
  dependency-version: 1.11.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-12 04:31:11 +00:00
dependabot[bot]
70edd4b898 Bump cgi from 0.3.6 to 0.3.7
Bumps [cgi](https://github.com/ruby/cgi) from 0.3.6 to 0.3.7.
- [Release notes](https://github.com/ruby/cgi/releases)
- [Commits](https://github.com/ruby/cgi/compare/v0.3.6...v0.3.7)

---
updated-dependencies:
- dependency-name: cgi
  dependency-version: 0.3.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-12 04:31:07 +00:00
dependabot[bot]
b57a2befd9 Bump rexml from 3.2.9 to 3.3.9
Bumps [rexml](https://github.com/ruby/rexml) from 3.2.9 to 3.3.9.
- [Release notes](https://github.com/ruby/rexml/releases)
- [Changelog](https://github.com/ruby/rexml/blob/master/NEWS.md)
- [Commits](https://github.com/ruby/rexml/compare/v3.2.9...v3.3.9)

---
updated-dependencies:
- dependency-name: rexml
  dependency-version: 3.3.9
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-12 04:27:20 +00:00
dependabot[bot]
fef9a78198 Bump thor from 1.3.1 to 1.4.0
Bumps [thor](https://github.com/rails/thor) from 1.3.1 to 1.4.0.
- [Release notes](https://github.com/rails/thor/releases)
- [Commits](https://github.com/rails/thor/compare/v1.3.1...v1.4.0)

---
updated-dependencies:
- dependency-name: thor
  dependency-version: 1.4.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-12 04:24:48 +00:00
Maikel
dd86736170 Merge pull request #13461 from openfoodfoundation/dependabot/bundler/webrick-1.8.2
Bump webrick from 1.8.1 to 1.8.2
2025-08-12 13:54:23 +10:00
Maikel
0d8c7ef118 Merge pull request #13460 from openfoodfoundation/dependabot/bundler/nokogiri-1.18.9
Bump nokogiri from 1.16.5 to 1.18.9
2025-08-12 13:52:57 +10:00
dependabot[bot]
20730b8768 Bump webrick from 1.8.1 to 1.8.2
Bumps [webrick](https://github.com/ruby/webrick) from 1.8.1 to 1.8.2.
- [Release notes](https://github.com/ruby/webrick/releases)
- [Commits](https://github.com/ruby/webrick/compare/v1.8.1...v1.8.2)

---
updated-dependencies:
- dependency-name: webrick
  dependency-version: 1.8.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-12 03:43:07 +00:00
dependabot[bot]
ad7c69189b Bump nokogiri from 1.16.5 to 1.18.9
Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.16.5 to 1.18.9.
- [Release notes](https://github.com/sparklemotion/nokogiri/releases)
- [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.16.5...v1.18.9)

---
updated-dependencies:
- dependency-name: nokogiri
  dependency-version: 1.18.9
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-12 03:22:15 +00:00
Maikel Linke
a5f44cb9b2 Update inflection config to Rails 7.0 template 2025-08-12 12:49:06 +10:00
Maikel Linke
97d21d8cbe Update parameter filtering to Rails 7.0 template 2025-08-12 12:45:48 +10:00
Maikel Linke
7afdd13b64 Update CSP config with Rails 7.0 template 2025-08-12 12:41:24 +10:00
Maikel Linke
54c446f0a3 Update asset config to Rails 7.0 templates 2025-08-12 12:30:30 +10:00
Maikel Linke
4454c90575 Update test config with Rails 7.0 template 2025-08-12 12:22:23 +10:00
Maikel Linke
dd3a61acdf Update production config with Rails 7.0 default 2025-08-12 12:10:22 +10:00
Maikel Linke
6d8ddd1eda Update development config with Rails 7.0 defaults 2025-08-12 12:10:19 +10:00
Maikel Linke
b8e8ab15d1 Update environment config with Rails 7.0 default 2025-08-12 11:06:33 +10:00
Maikel Linke
bf1d2f3620 Update boot config from Rails 7.0 template 2025-08-12 10:59:46 +10:00
Maikel Linke
43026ddc6a Update application config with Rails 7.0 defaults 2025-08-12 10:56:34 +10:00
Maikel Linke
18b83d2423 Add Rails 7.0 framework defaults templates 2025-08-12 10:42:37 +10:00
Maikel Linke
3a72aefc1c Fail test when timeout reached
In this example it didn't matter but if we re-use the helper then it
needs to raise an error after the timeout has been reached.
2025-08-12 09:54:48 +10:00
David Cook
e855ea0dbd Merge pull request #13453 from mkllnk/rails-7.1
Allow only existing deprecations in Rails 7.1
2025-08-12 09:44:25 +10:00
David Cook
1eba950e19 Merge pull request #13451 from mkllnk/remove-person
Remove Person from product catalog
2025-08-12 09:42:40 +10:00
David Cook
9cd04c087e Merge pull request #13450 from mkllnk/engine-ruby-version
Losen engine gemspec requirement for Dependabot
2025-08-12 09:40:01 +10:00
David Cook
459d25e533 Merge pull request #13447 from mkllnk/cover-rake
Report code coverage on rake tasks
2025-08-12 09:37:51 +10:00
Kirst
b06e562425 Remove flatpickr controller test that isn't useful based on feedback 2025-08-11 20:29:11 +10:00
Kirst
2936cfebca Remove I18n assignment from flatpickr controller test from feedback 2025-08-11 20:29:11 +10:00
Kirst
b8ad428b5d Load only specified flatpickr locale
Dynamically import only the requested flatpickr locale.

English locale is bundled by default, so passing null triggers flatpickr's built-in English fallback without an explicit import.
2025-08-11 20:28:47 +10:00
Maikel Linke
ca34d24847 Replace long waits with better polling
Capybara polls under the hood as well. So we do something similar here
but tailored to the tested code. This reduced the test run time on my
machine from 35 seconds to 15 seconds.
2025-08-11 17:07:44 +10:00
Maikel Linke
6e581fce75 Remove unnecessary styling
The early dev versions of the DPM needed these styles. Now the module
looks fine without any additional styles.
2025-08-11 16:29:08 +10:00
Gaetan Craig-Riou
66041061fb Redeem VINE voucher before redirecting to payment url
When using paypal, we need to redeem the voucher before redirecting to
the payment gateway url, otherwise the voucher will never get redeemed.
2025-08-11 16:28:04 +10:00
Maikel Linke
e54c27c900 Use more precise regex 2025-08-11 16:23:08 +10:00
Maikel Linke
b3d3d6bf06 Allow DPM feature for specific users 2025-08-11 15:25:50 +10:00
Maikel Linke
5876c52318 Test all known scopes 2025-08-11 15:15:00 +10:00
Maikel Linke
842f4ae40e Re-enable CSRF check supported by DPM now 2025-08-11 15:13:35 +10:00
Maikel Linke
342ef4e9eb Complete smoke test of DFC data sharing
Working within a shadow root of the web component isn't well supported
by Capybara and I needed to find some workarounds. It's not pretty but
it works (on my machine). *fingers crossed*
2025-08-08 14:00:41 +10:00
Maikel Linke
210201514e Add gem capybara-shadowdom to access web component 2025-08-08 14:00:41 +10:00
Maikel Linke
2d3f18a71b Load DFC Permissions module in system spec
But we can't access the inside of the component yet.
2025-08-08 14:00:41 +10:00
Maikel Linke
9d284b7110 Set language to display scope labels 2025-08-08 14:00:41 +10:00
Maikel Linke
994f1ca6c6 Update scope ids 2025-08-08 14:00:41 +10:00
Maikel Linke
f65e4797cf Add feature toggle for DFC dev platform 2025-08-08 14:00:40 +10:00
Maikel Linke
52aeec5ac4 Update and list scopes for real 2025-08-08 14:00:40 +10:00
Maikel Linke
7032b3f463 Add endpoint to update scopes of platform
Dummy implementation only.
2025-08-08 14:00:40 +10:00
Maikel Linke
c26686b430 Add DfcPermission model to persist granted scopes 2025-08-08 14:00:38 +10:00
Maikel Linke
60c8f4ee20 Add DFC API endpoint for listing platforms
Only listing example JSON for now.

This is not part of the official DFC API but it's a DFC-related API and
therefore we put it in the same namespace.

The DFC Permission Module will make authenticated requests to grant
certain platforms certain permissions.
2025-08-08 14:00:01 +10:00
Maikel Linke
25f396c126 Add permission module with example data
It's basically just copied from the Readme file still pointing to the
development server and it's not interacting with OFN just yet.
2025-08-08 14:00:01 +10:00
Maikel Linke
0166abcd2a Remove deprecated and unnecessary config 2025-08-08 11:18:34 +10:00
Maikel Linke
4cd0071dd4 Allow only existing deprecations
* Allow deprecated cache_format_version
* Allow deprecated Rails.application.secrets
* Allow deprecated Passing the class as positional argument
* Allow deprecated alias_attribute with non-attribute targets
* Allow deprecated model aliases
* Allow deprecated action_dispatch.show_exceptions
2025-08-08 11:17:41 +10:00
Maikel Linke
1ec570375f Remove Person from product catalog
Early versions of the DFC standard demanded that all data is published
in relationship to the authenticated user. But that is not necessary
anymore and can add complications when a platform is authenticated as
client user.
2025-08-07 14:56:35 +10:00
Maikel Linke
75c33b29d5 Losen engine gemspec requirement for Dependabot
Dependabot doesn't seem to be able to resolve the version correctly. We
got this message:

```
Could not find compatible versions

Because every version of web depends on Ruby = 0.0.1
  and Gemfile depends on web >= 0,
  Ruby = 0.0.1 is required.
So, because current Ruby version is = 3.1.4,
  version solving has failed.
```
2025-08-07 12:59:32 +10:00
Gareth
3750898c44 Looks like db:prepare never fully ran and that's why it did not work. The issue seems to be using foreman with web, webpack, and sidekiq in the same script. Though not dependent on each other, the build order or port assignment was causing web to exit early upon build 2025-08-06 15:21:30 -04:00
Gareth
d34f8900d7 divided foreman queued services into 3 containers. Web was exiting seemingly at random and seems to be a conflict between web, web-pack, and sidekiq being run through foreman. The division into 3 dev containers has been very consistent in building the project correctly 2025-08-06 15:05:45 -04:00
Maikel
910ded1a8c Typo
[skip ci]
2025-08-05 13:49:44 +10:00
Maikel Linke
2555a9e710 Ignore breaking code coverage for coverage spec
When we test our code coverage compilation, it breaks the code coverage
report for the current rspec process. By running that code separately,
we gain a correct coverage report for the rest of the code again.

So unfortunately, we can't report on the code coverage of this
particular task and have to ignore it. But at least CI depends on the
correct function of this task and would fail if it didn't work.
2025-08-05 12:45:05 +10:00
Maikel Linke
f532c4712e Load rake tasks only once for code coverage
Apparently, Rake's way of reloading the task code confuses the code
coverage report. Code tested by rake task specs was not recognised as
covered even though it was.
2025-08-05 12:44:13 +10:00
Gareth
addf36a304 dummy commit for docker token check 2025-07-30 20:44:05 -04:00
Gareth
6a912b7d8c Added cmake dep to dockerfile and added script for db:schema:load that runs only if the schema is different than the latest migration 2025-07-30 20:12:53 -04:00
cyrillefr
8011449ce7 Adding a spec with one single tag
- need to add ids to ru the spec
2025-07-14 18:15:01 +02:00
cyrillefr
be0894653a Fixes Save button does not enable when removing only tag in OC 2025-06-30 12:41:41 +02:00
319 changed files with 60675 additions and 2742 deletions

15
.github/test-events/dependabot-pr.json vendored Normal file
View File

@@ -0,0 +1,15 @@
{
"pull_request": {
"number": 13545,
"title": "Bump test from 7.0.4 to 7.0.8",
"user": {
"login": "dependabot[bot]"
}
},
"repository": {
"owner": {
"login": "openfoodfoundation"
},
"name": "openfoodnetwork"
}
}

View File

@@ -0,0 +1,151 @@
name: Auto-move Dependabot PRs to Code Review
permissions:
contents: read
pull-requests: read
on:
pull_request_target:
types: [opened]
jobs:
move-pr-to-code-review:
runs-on: ubuntu-latest
if: github.event.pull_request.user.login == 'dependabot[bot]' || startsWith(github.event.pull_request.title, 'Bump')
steps:
- name: Generate GitHub App Token
id: app-token
uses: tibdex/github-app-token@v2
with:
app_id: ${{ secrets.DEPENDABOT_PR_APP_ID }}
private_key: ${{ secrets.DEPENDABOT_PR_APP_PRIVATE_KEY }}
installation_retrieval_mode: id
installation_retrieval_payload: ${{ secrets.DEPENDABOT_PR_APP_INSTALLATION_ID }}
- name: Move PR to Code Review in Project v2
uses: actions/github-script@v7
with:
github-token: ${{ steps.app-token.outputs.token }}
script: |
const projectNumber = 8; // for "OFN Delivery board"
const org = "openfoodfoundation";
const repo = context.repo.repo;
const prNumber = context.payload.pull_request.number;
const statusFieldName = "Status";
const statusValue = "Code review 🔎";
// ---- Helper: Get PR Node ID ----
async function getPrNodeId(owner, repo, number) {
const res = await github.graphql(`
query($owner: String!, $repo: String!, $number: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $number) {
id
number
title
}
}
}
`, { owner, repo, number });
return res.repository.pullRequest.id;
}
console.log("🚀 Starting ProjectV2 automation...");
// ---- Step 1: Get Project and Fields ----
const projectRes = await github.graphql(`
query($org: String!, $number: Int!) {
organization(login: $org) {
projectV2(number: $number) {
id
title
fields(first: 50) {
nodes {
... on ProjectV2Field {
id
name
}
... on ProjectV2SingleSelectField {
id
name
options {
id
name
}
}
}
}
}
}
}
`, { org, number: projectNumber });
const project = projectRes.organization.projectV2;
if (!project) throw new Error(`❌ Project #${projectNumber} not found`);
console.log(`✅ Found project: ${project.title} (${project.id})`);
const statusField = project.fields.nodes.find(f => f.name === statusFieldName);
if (!statusField) throw new Error(`❌ Field '${statusFieldName}' not found`);
const option = statusField.options.find(o => o.name === statusValue);
if (!option) throw new Error(`❌ Option '${statusValue}' not found in '${statusFieldName}'`);
console.log(`✅ Found field '${statusFieldName}' and option '${statusValue}'`);
// ---- Step 2: Get PR Node ID ----
const prNodeId = await getPrNodeId(org, repo, prNumber);
console.log(`✅ PR #${prNumber} node ID: ${prNodeId}`);
// ---- Step 3: Check if PR is already in Project ----
const itemRes = await github.graphql(`
query($prId: ID!) {
node(id: $prId) {
... on PullRequest {
projectItems(first: 50) {
nodes {
id
project { id title }
}
}
}
}
}
`, { prId: prNodeId });
let projectItem = itemRes.node.projectItems.nodes.find(i => i.project.id === project.id);
if (!projectItem) {
console.log(" PR not yet in project, adding...");
const addRes = await github.graphql(`
mutation($projectId: ID!, $contentId: ID!) {
addProjectV2ItemById(input: {projectId: $projectId, contentId: $contentId}) {
item { id }
}
}
`, { projectId: project.id, contentId: prNodeId });
projectItem = addRes.addProjectV2ItemById.item;
console.log(`✅ Added PR to project: ${projectItem.id}`);
} else {
console.log(` PR already in project: ${projectItem.id}`);
}
// ---- Step 4: Update Status ----
await github.graphql(`
mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $optionId: String!) {
updateProjectV2ItemFieldValue(input: {
projectId: $projectId,
itemId: $itemId,
fieldId: $fieldId,
value: { singleSelectOptionId: $optionId }
}) {
projectV2Item { id }
}
}
`, {
projectId: project.id,
itemId: projectItem.id,
fieldId: statusField.id,
optionId: option.id,
});
console.log(`🎉 Moved PR #${prNumber} → '${statusValue}'`);

1
.gitignore vendored
View File

@@ -59,3 +59,4 @@ yarn-debug.log*
/config/credentials.yml.enc
/config/master.key
.secrets

View File

@@ -47,7 +47,7 @@ Metrics/BlockNesting:
Exclude:
- 'app/models/spree/payment/processing.rb'
# Offense count: 47
# Offense count: 48
# Configuration parameters: CountComments, Max, CountAsOne.
Metrics/ClassLength:
Exclude:
@@ -88,6 +88,7 @@ Metrics/ClassLength:
- 'app/services/cart_service.rb'
- 'app/services/order_cycles/form_service.rb'
- 'app/services/orders/sync_service.rb'
- 'app/services/permissions/order.rb'
- 'app/services/sets/product_set.rb'
- 'engines/order_management/app/services/order_management/order/updater.rb'
- 'lib/open_food_network/enterprise_fee_calculator.rb'
@@ -98,7 +99,6 @@ Metrics/ClassLength:
- 'lib/reporting/reports/enterprise_fee_summary/enterprise_fees_with_tax_report_by_producer.rb'
- 'lib/reporting/reports/enterprise_fee_summary/scope.rb'
- 'lib/reporting/reports/xero_invoices/base.rb'
- 'app/services/permissions/order.rb'
# Offense count: 30
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
@@ -129,14 +129,13 @@ Metrics/CyclomaticComplexity:
- 'lib/spree/localized_number.rb'
- 'spec/models/product_importer_spec.rb'
# Offense count: 23
# Offense count: 22
# Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns.
Metrics/MethodLength:
Exclude:
- 'app/controllers/admin/enterprises_controller.rb'
- 'app/controllers/payment_gateways/paypal_controller.rb'
- 'app/controllers/spree/orders_controller.rb'
- 'app/helpers/spree/admin/navigation_helper.rb'
- 'app/models/spree/ability.rb'
- 'app/models/spree/gateway/pay_pal_express.rb'
- 'app/models/spree/order/checkout.rb'
@@ -149,7 +148,7 @@ Metrics/MethodLength:
- 'lib/spree/localized_number.rb'
- 'lib/tasks/sample_data/product_factory.rb'
# Offense count: 47
# Offense count: 10
# Configuration parameters: CountComments, Max, CountAsOne.
Metrics/ModuleLength:
Exclude:
@@ -174,7 +173,7 @@ Metrics/ParameterLists:
- 'spec/support/controller_requests_helper.rb'
- 'spec/system/admin/reports_spec.rb'
# Offense count: 3
# Offense count: 4
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
Metrics/PerceivedComplexity:
Exclude:
@@ -182,6 +181,27 @@ Metrics/PerceivedComplexity:
- 'app/models/spree/ability.rb'
- 'app/models/spree/order/checkout.rb'
# Offense count: 1
# Configuration parameters: EnforcedStyle, AllowedPatterns.
# SupportedStyles: snake_case, camelCase
Naming/MethodName:
Exclude:
- 'engines/dfc_provider/lib/dfc_provider/catalog_item.rb'
# Offense count: 1
# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
# AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to
Naming/MethodParameterName:
Exclude:
- 'engines/dfc_provider/lib/dfc_provider/catalog_item.rb'
# Offense count: 3
# Configuration parameters: EnforcedStyle, AllowedIdentifiers, AllowedPatterns.
# SupportedStyles: snake_case, camelCase
Naming/VariableName:
Exclude:
- 'engines/dfc_provider/lib/dfc_provider/catalog_item.rb'
# Offense count: 1
# Configuration parameters: TransactionMethods.
Rails/TransactionExitStatement:

4
.secrets.example Normal file
View File

@@ -0,0 +1,4 @@
# .secrets file define github secrets value locally
DEPENDABOT_PR_APP_ID=123456
DEPENDABOT_PR_APP_INSTALLATION_ID=123456
DEPENDABOT_PR_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n....\n-----END RSA PRIVATE KEY-----"

View File

@@ -2,13 +2,17 @@
# frozen_string_literal: true
SimpleCov.start 'rails' do
# The rails profile contains some filters already:
#
# - "/test/"
# - "/features/"
# - "/spec/"
# - "/autotest/"
# - /^\/config\//
# - /^\/db\//
add_filter '/bin/'
add_filter '/config/'
add_filter '/config/' # to include engine config
add_filter '/script'
add_filter '/db'
# We haven't managed to make simplecov recognise rake coverage accurately.
add_filter '/lib/tasks/'
formatter SimpleCov::Formatter::SimpleFormatter
end

View File

@@ -1,4 +1,9 @@
#!/bin/env ruby
# frozen_string_literal: true
-c master
--compare master
# This shouldn't be needed in undercover > 0.7.4
#
# * https://github.com/grodowski/undercover/issues/233
--exclude-files "bin/*,db/*,config/*,spec/*,engines/*/config/*,engines/*/spec/*"

View File

@@ -2,7 +2,9 @@ FROM ruby:3.1.4-alpine3.19 AS base
ENV LANG=C.UTF-8 \
LC_ALL=C.UTF-8 \
TZ=Europe/London \
RAILS_ROOT=/usr/src/app
RAILS_ROOT=/usr/src/app \
BUNDLE_PATH=/bundles \
BUNDLE_APP_CONFIG=/bundles
RUN apk --no-cache upgrade && \
apk add --no-cache tzdata postgresql-client imagemagick imagemagick-jpeg && \
apk add --no-cache --virtual wkhtmltopdf
@@ -14,7 +16,7 @@ FROM base AS development-base
RUN apk add --no-cache --virtual .build-deps \
build-base postgresql-dev git nodejs yarn && \
apk add --no-cache --virtual .dev-utils \
bash curl less vim chromium-chromedriver zlib-dev openssl-dev \
bash curl less vim chromium-chromedriver zlib-dev openssl-dev cmake\
readline-dev yaml-dev sqlite-dev libxml2-dev libxslt-dev libffi-dev vips-dev && \
curl -o /usr/local/bin/wait-for-it https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh && \
chmod +x /usr/local/bin/wait-for-it

View File

@@ -25,7 +25,8 @@ RUN apt-get update && apt-get install -y \
libjemalloc-dev \
libssl-dev \
ca-certificates \
gnupg
gnupg \
cmake
# Setup ENV variables
ENV PATH /usr/local/src/rbenv/shims:/usr/local/src/rbenv/bin:/usr/local/src/nodenv/shims:/usr/local/src/nodenv/bin:$PATH

View File

@@ -73,7 +73,7 @@ To login as the default user, use:
email: ofn@example.com
password: ofn123
Seee [Locale and sample data] about loading data.
See [Locale and sample data] about loading data.
### Testing

View File

@@ -20,6 +20,10 @@ gem 'ransack', '~> 4.1.0'
gem 'responders'
gem 'webpacker', '~> 5'
# Indirect dependency but we access it directly in JS specs.
# It turns out to be hard to upgrade but please do if you can.
gem 'sprockets', '~> 3.7'
gem 'i18n'
gem 'i18n-js', '~> 3.9.0'
gem 'rails-i18n'
@@ -152,6 +156,7 @@ end
group :test, :development do
gem 'bullet'
gem 'capybara'
gem 'capybara-shadowdom'
gem 'cuprite'
gem 'database_cleaner', require: false
gem 'debug', '>= 1.0.0'
@@ -166,7 +171,6 @@ group :test, :development do
gem 'rswag'
gem 'shoulda-matchers'
gem 'stimulus_reflex_testing', github: "podia/stimulus_reflex_testing", branch: :main
gem 'timecop'
end
group :test do

View File

@@ -48,36 +48,36 @@ PATH
GEM
remote: https://rubygems.org/
specs:
Ascii85 (1.1.0)
actioncable (7.1.5.1)
actionpack (= 7.1.5.1)
activesupport (= 7.1.5.1)
Ascii85 (2.0.1)
actioncable (7.1.5.2)
actionpack (= 7.1.5.2)
activesupport (= 7.1.5.2)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6)
actionmailbox (7.1.5.1)
actionpack (= 7.1.5.1)
activejob (= 7.1.5.1)
activerecord (= 7.1.5.1)
activestorage (= 7.1.5.1)
activesupport (= 7.1.5.1)
actionmailbox (7.1.5.2)
actionpack (= 7.1.5.2)
activejob (= 7.1.5.2)
activerecord (= 7.1.5.2)
activestorage (= 7.1.5.2)
activesupport (= 7.1.5.2)
mail (>= 2.7.1)
net-imap
net-pop
net-smtp
actionmailer (7.1.5.1)
actionpack (= 7.1.5.1)
actionview (= 7.1.5.1)
activejob (= 7.1.5.1)
activesupport (= 7.1.5.1)
actionmailer (7.1.5.2)
actionpack (= 7.1.5.2)
actionview (= 7.1.5.2)
activejob (= 7.1.5.2)
activesupport (= 7.1.5.2)
mail (~> 2.5, >= 2.5.4)
net-imap
net-pop
net-smtp
rails-dom-testing (~> 2.2)
actionpack (7.1.5.1)
actionview (= 7.1.5.1)
activesupport (= 7.1.5.1)
actionpack (7.1.5.2)
actionview (= 7.1.5.2)
activesupport (= 7.1.5.2)
nokogiri (>= 1.8.5)
racc
rack (>= 2.2.4)
@@ -87,15 +87,15 @@ GEM
rails-html-sanitizer (~> 1.6)
actionpack-action_caching (1.2.2)
actionpack (>= 4.0.0)
actiontext (7.1.5.1)
actionpack (= 7.1.5.1)
activerecord (= 7.1.5.1)
activestorage (= 7.1.5.1)
activesupport (= 7.1.5.1)
actiontext (7.1.5.2)
actionpack (= 7.1.5.2)
activerecord (= 7.1.5.2)
activestorage (= 7.1.5.2)
activesupport (= 7.1.5.2)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (7.1.5.1)
activesupport (= 7.1.5.1)
actionview (7.1.5.2)
activesupport (= 7.1.5.2)
builder (~> 3.1)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
@@ -107,8 +107,8 @@ GEM
activemodel (>= 5.2.0)
activestorage (>= 5.2.0)
activesupport (>= 5.2.0)
activejob (7.1.5.1)
activesupport (= 7.1.5.1)
activejob (7.1.5.2)
activesupport (= 7.1.5.2)
globalid (>= 0.3.6)
activemerchant (1.133.0)
activesupport (>= 4.2)
@@ -116,11 +116,11 @@ GEM
i18n (>= 0.6.9)
nokogiri (~> 1.4)
rexml (~> 3.2.5)
activemodel (7.1.5.1)
activesupport (= 7.1.5.1)
activerecord (7.1.5.1)
activemodel (= 7.1.5.1)
activesupport (= 7.1.5.1)
activemodel (7.1.5.2)
activesupport (= 7.1.5.2)
activerecord (7.1.5.2)
activemodel (= 7.1.5.2)
activesupport (= 7.1.5.2)
timeout (>= 0.4.0)
activerecord-import (1.6.0)
activerecord (>= 4.2)
@@ -133,13 +133,13 @@ GEM
multi_json (~> 1.11, >= 1.11.2)
rack (>= 2.0.8, < 4)
railties (>= 6.1)
activestorage (7.1.5.1)
actionpack (= 7.1.5.1)
activejob (= 7.1.5.1)
activerecord (= 7.1.5.1)
activesupport (= 7.1.5.1)
activestorage (7.1.5.2)
actionpack (= 7.1.5.2)
activejob (= 7.1.5.2)
activerecord (= 7.1.5.2)
activesupport (= 7.1.5.2)
marcel (~> 1.0)
activesupport (7.1.5.1)
activesupport (7.1.5.2)
base64
benchmark (>= 0.3)
bigdecimal
@@ -189,7 +189,7 @@ GEM
aws-sigv4 (~> 1.8)
aws-sigv4 (1.8.0)
aws-eventstream (~> 1, >= 1.0.2)
base64 (0.2.0)
base64 (0.3.0)
bcp47_spec (0.2.1)
bcrypt (3.1.20)
benchmark (0.4.1)
@@ -200,8 +200,8 @@ GEM
msgpack (~> 1.2)
bugsnag (6.26.4)
concurrent-ruby (~> 1.0)
builder (3.2.4)
bullet (7.1.6)
builder (3.3.0)
bullet (8.0.8)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11)
cable_ready (5.0.6)
@@ -221,12 +221,14 @@ GEM
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
capybara-shadowdom (0.3.0)
capybara
caxlsx (3.3.0)
htmlentities (~> 4.3, >= 4.3.4)
marcel (~> 1.0)
nokogiri (~> 1.10, >= 1.10.4)
rubyzip (>= 1.3.0, < 3)
cgi (0.3.6)
cgi (0.5.0)
childprocess (5.0.0)
choice (0.2.0)
chronic (0.10.2)
@@ -241,8 +243,8 @@ GEM
combine_pdf (1.0.26)
matrix
ruby-rc4 (>= 0.1.5)
concurrent-ruby (1.3.1)
connection_pool (2.4.1)
concurrent-ruby (1.3.5)
connection_pool (2.5.4)
cookiejar (0.3.4)
crack (1.0.0)
bigdecimal
@@ -262,7 +264,7 @@ GEM
database_cleaner-core (2.0.1)
datafoodconsortium-connector (1.1.0)
virtual_assembly-semantizer (~> 1.0, >= 1.0.5)
date (3.3.4)
date (3.4.1)
debug (1.9.2)
irb (~> 1.10)
reline (>= 0.3.8)
@@ -279,9 +281,9 @@ GEM
devise (>= 4.9.0)
devise-token_authenticatable (1.1.0)
devise (>= 4.0.0, < 5.0.0)
diff-lcs (1.5.1)
digest (3.1.1)
docile (1.4.0)
diff-lcs (1.6.2)
digest (3.2.0)
docile (1.4.1)
dotenv (3.1.2)
drb (2.2.3)
em-http-request (1.1.7)
@@ -297,8 +299,10 @@ GEM
eventmachine (>= 1.0.0.beta.1)
email_validator (2.2.4)
activemodel
erubi (1.12.0)
et-orbi (1.2.7)
erb (4.0.4)
cgi (>= 0.3.3)
erubi (1.13.1)
et-orbi (1.3.0)
tzinfo
eventmachine (1.2.7)
eventmachine_httpserver (0.2.1)
@@ -322,7 +326,7 @@ GEM
websocket-driver (>= 0.6, < 0.8)
ffaker (2.23.0)
ffi (1.16.3)
flipper (1.3.0)
flipper (1.3.6)
concurrent-ruby (< 2)
flipper-active_record (1.3.0)
activerecord (>= 4.2, < 8)
@@ -351,8 +355,8 @@ GEM
nokogiri (>= 1.5.11, < 2.0.0)
foreman (0.88.1)
formatador (0.2.5)
fugit (1.8.1)
et-orbi (~> 1, >= 1.2.7)
fugit (1.11.1)
et-orbi (~> 1, >= 1.2.11)
raabro (~> 1.4)
fuubar (2.5.1)
rspec-core (~> 3.0)
@@ -399,10 +403,11 @@ GEM
activerecord (>= 3.0)
invisible_captcha (2.3.0)
rails (>= 5.2)
io-console (0.7.2)
io-console (0.8.1)
ipaddress (0.8.3)
irb (1.12.0)
rdoc
irb (1.15.2)
pp (>= 0.6.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
jmespath (1.6.2)
jquery-rails (4.4.0)
@@ -450,7 +455,7 @@ GEM
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
logger (1.7.0)
loofah (2.22.0)
loofah (2.24.1)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.8.1)
@@ -461,16 +466,17 @@ GEM
marcel (1.0.4)
matrix (0.4.2)
method_source (1.1.0)
mime-types (3.5.2)
mime-types-data (~> 3.2015)
mime-types-data (3.2023.1205)
mime-types (3.7.0)
logger
mime-types-data (~> 3.2025, >= 3.2025.0507)
mime-types-data (3.2025.0924)
mimemagic (0.4.3)
nokogiri (~> 1)
rake
mini_magick (4.11.0)
mini_mime (1.1.5)
mini_portile2 (2.8.6)
minitest (5.23.1)
minitest (5.25.5)
monetize (1.13.0)
money (~> 6.12)
money (6.16.0)
@@ -481,7 +487,7 @@ GEM
mutex_m (0.3.0)
net-http (0.4.1)
uri
net-imap (0.4.10)
net-imap (0.4.20)
date
net-protocol
net-pop (0.1.2)
@@ -490,9 +496,9 @@ GEM
timeout
net-smtp (0.5.0)
net-protocol
newrelic_rpm (9.9.0)
newrelic_rpm (9.22.0)
nio4r (2.7.1)
nokogiri (1.16.5)
nokogiri (1.18.10)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
nokogiri-html5-inference (0.3.0)
@@ -536,7 +542,7 @@ GEM
parallel (1.24.0)
paranoia (2.6.3)
activerecord (>= 5.1, < 7.2)
parser (3.3.8.0)
parser (3.3.9.0)
ast (~> 2.4.1)
racc
paypal-sdk-core (0.3.4)
@@ -544,18 +550,22 @@ GEM
xml-simple
paypal-sdk-merchant (1.117.2)
paypal-sdk-core (~> 0.3.0)
pdf-reader (2.12.0)
Ascii85 (~> 1.0)
afm (~> 0.2.1)
pdf-reader (2.15.0)
Ascii85 (>= 1.0, < 3.0, != 2.0.0)
afm (>= 0.2.1, < 2)
hashery (~> 2.0)
ruby-rc4
ttfunk
pg (1.2.3)
pp (0.6.2)
prettyprint
prettyprint (0.2.0)
private_address_check (0.5.0)
pry (0.13.1)
coderay (~> 1.1)
method_source (~> 1.0)
psych (5.1.2)
psych (5.2.6)
date
stringio
public_suffix (5.0.5)
puffing-billy (4.0.2)
@@ -573,7 +583,7 @@ GEM
railties (>= 4.2)
raabro (1.4.0)
racc (1.8.1)
rack (2.2.11)
rack (2.2.20)
rack-mini-profiler (2.3.4)
rack (>= 1.2.0)
rack-oauth2 (2.2.1)
@@ -591,31 +601,31 @@ GEM
rack-rewrite (1.5.1)
rack-session (1.0.2)
rack (< 3)
rack-test (2.1.0)
rack-test (2.2.0)
rack (>= 1.3)
rack-timeout (0.7.0)
rackup (1.0.1)
rack (< 3)
webrick
rails (7.1.5.1)
actioncable (= 7.1.5.1)
actionmailbox (= 7.1.5.1)
actionmailer (= 7.1.5.1)
actionpack (= 7.1.5.1)
actiontext (= 7.1.5.1)
actionview (= 7.1.5.1)
activejob (= 7.1.5.1)
activemodel (= 7.1.5.1)
activerecord (= 7.1.5.1)
activestorage (= 7.1.5.1)
activesupport (= 7.1.5.1)
rails (7.1.5.2)
actioncable (= 7.1.5.2)
actionmailbox (= 7.1.5.2)
actionmailer (= 7.1.5.2)
actionpack (= 7.1.5.2)
actiontext (= 7.1.5.2)
actionview (= 7.1.5.2)
activejob (= 7.1.5.2)
activemodel (= 7.1.5.2)
activerecord (= 7.1.5.2)
activestorage (= 7.1.5.2)
activesupport (= 7.1.5.2)
bundler (>= 1.15.0)
railties (= 7.1.5.1)
railties (= 7.1.5.2)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1)
activesupport (>= 5.0.1.rc1)
rails-dom-testing (2.2.0)
rails-dom-testing (2.3.0)
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
@@ -624,23 +634,23 @@ GEM
activesupport (>= 4.2)
choice (~> 0.2.0)
ruby-graphviz (~> 1.2)
rails-html-sanitizer (1.6.0)
rails-html-sanitizer (1.6.2)
loofah (~> 2.21)
nokogiri (~> 1.14)
rails-i18n (7.0.9)
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
rails-i18n (7.0.10)
i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 8)
rails_safe_tasks (1.0.0)
railties (7.1.5.1)
actionpack (= 7.1.5.1)
activesupport (= 7.1.5.1)
railties (7.1.5.2)
actionpack (= 7.1.5.2)
activesupport (= 7.1.5.2)
irb
rackup (>= 1.0.0)
rake (>= 12.2)
thor (~> 1.0, >= 1.2.2)
zeitwerk (~> 2.6)
rainbow (3.1.1)
rake (13.2.1)
rake (13.3.0)
ransack (4.1.1)
activerecord (>= 6.1.5)
activesupport (>= 6.1.5)
@@ -652,15 +662,17 @@ GEM
bcp47_spec (~> 0.2)
bigdecimal (~> 3.1, >= 3.1.5)
link_header (~> 0.0, >= 0.0.8)
rdoc (6.6.3.1)
rdoc (6.15.0)
erb
psych (>= 4.0.0)
tsort
redcarpet (3.6.0)
redis (5.2.0)
redis (5.4.1)
redis-client (>= 0.22.0)
redis-client (0.22.1)
redis-client (0.26.1)
connection_pool
regexp_parser (2.9.2)
reline (0.5.0)
reline (0.6.2)
io-console (~> 0.5)
request_store (1.5.1)
rack (>= 1.4)
@@ -685,18 +697,18 @@ GEM
rspec-core (~> 3.13.0)
rspec-expectations (~> 3.13.0)
rspec-mocks (~> 3.13.0)
rspec-core (3.13.0)
rspec-core (3.13.5)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.0)
rspec-expectations (3.13.5)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.0)
rspec-mocks (3.13.5)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-rails (6.1.2)
actionpack (>= 6.1)
activesupport (>= 6.1)
railties (>= 6.1)
rspec-rails (7.1.1)
actionpack (>= 7.0)
activesupport (>= 7.0)
railties (>= 7.0)
rspec-core (~> 3.13)
rspec-expectations (~> 3.13)
rspec-mocks (~> 3.13)
@@ -706,22 +718,22 @@ GEM
rspec-sql (0.0.3)
activesupport
rspec
rspec-support (3.13.1)
rswag (2.13.0)
rswag-api (= 2.13.0)
rswag-specs (= 2.13.0)
rswag-ui (= 2.13.0)
rswag-api (2.13.0)
activesupport (>= 3.1, < 7.2)
railties (>= 3.1, < 7.2)
rswag-specs (2.13.0)
activesupport (>= 3.1, < 7.2)
json-schema (>= 2.2, < 5.0)
railties (>= 3.1, < 7.2)
rspec-support (3.13.6)
rswag (2.16.0)
rswag-api (= 2.16.0)
rswag-specs (= 2.16.0)
rswag-ui (= 2.16.0)
rswag-api (2.16.0)
activesupport (>= 5.2, < 8.1)
railties (>= 5.2, < 8.1)
rswag-specs (2.16.0)
activesupport (>= 5.2, < 8.1)
json-schema (>= 2.2, < 6.0)
railties (>= 5.2, < 8.1)
rspec-core (>= 2.14)
rswag-ui (2.13.0)
actionpack (>= 3.1, < 7.2)
railties (>= 3.1, < 7.2)
rswag-ui (2.16.0)
actionpack (>= 5.2, < 8.1)
railties (>= 5.2, < 8.1)
rubocop (1.64.1)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
@@ -789,7 +801,7 @@ GEM
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1)
simplecov-html (0.12.3)
simplecov-html (0.13.2)
simplecov_json_formatter (0.1.4)
spreadsheet_architect (5.0.0)
caxlsx (>= 3.3.0, < 4)
@@ -799,7 +811,8 @@ GEM
spring (>= 0.9.1)
spring-commands-rubocop (0.4.0)
spring (>= 1.0)
sprockets (3.7.2)
sprockets (3.7.5)
base64
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.4.2)
@@ -826,7 +839,7 @@ GEM
railties (>= 5.2)
redis (>= 4.0, < 6.0)
stringex (2.8.6)
stringio (3.1.0)
stringio (3.1.7)
stripe (11.1.0)
strscan (3.1.2)
swd (2.0.3)
@@ -837,12 +850,13 @@ GEM
temple (0.8.2)
terminal-table (4.0.0)
unicode-display_width (>= 1.1.1, < 4)
thor (1.3.1)
thor (1.4.0)
thread-local (1.1.0)
tilt (2.3.0)
timecop (0.9.8)
timeout (0.4.1)
ttfunk (1.7.0)
timeout (0.4.3)
tsort (0.2.0)
ttfunk (1.8.0)
bigdecimal (~> 3.1)
turbo-rails (2.0.5)
actionpack (>= 6.0.0)
activejob (>= 6.0.0)
@@ -851,7 +865,7 @@ GEM
turbo-rails (>= 1.3.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
undercover (0.7.4)
undercover (0.8.1)
base64
bigdecimal
imagen (>= 0.2.0)
@@ -860,8 +874,8 @@ GEM
simplecov
simplecov_json_formatter
unicode-display_width (2.5.0)
uniform_notifier (1.16.0)
uri (0.13.0)
uniform_notifier (1.17.0)
uri (0.13.2)
valid_email2 (5.2.3)
activemodel (>= 3.2)
mail (~> 2.5)
@@ -901,7 +915,7 @@ GEM
rack-proxy (>= 0.6.1)
railties (>= 5.2)
semantic_range (>= 2.3.0)
webrick (1.8.1)
webrick (1.9.1)
websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
@@ -909,11 +923,11 @@ GEM
chronic (>= 0.6.3)
wicked_pdf (2.8.1)
activesupport
wkhtmltopdf-binary (0.12.6.7)
wkhtmltopdf-binary (0.12.6.10)
xml-simple (1.1.8)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.6.15)
zeitwerk (2.6.18)
PLATFORMS
ruby
@@ -941,6 +955,7 @@ DEPENDENCIES
cable_ready
cancancan (~> 1.15.0)
capybara
capybara-shadowdom
catalog!
coffee-rails (~> 5.0.0)
combine_pdf
@@ -1040,12 +1055,12 @@ DEPENDENCIES
spring
spring-commands-rspec
spring-commands-rubocop
sprockets (~> 3.7)
state_machines-activerecord
stimulus_reflex
stimulus_reflex_testing!
stringex (~> 2.8.5)
stripe
timecop
turbo-rails
turbo_power
undercover

View File

@@ -6,7 +6,6 @@ angular.module("admin.enterprises", [
"admin.side_menu",
"admin.taxons",
'admin.indexUtils',
'admin.tagRules',
'admin.dropdown',
'ngSanitize']
)

View File

@@ -15,4 +15,4 @@ angular.module("admin.paymentMethods").controller "StripeController", ($scope, $
permalink = shops.filter((shop) ->
shop.id == $scope.paymentMethod.preferred_enterprise_id
)[0].permalink
"/admin/enterprises/#{permalink}/edit#/payment_methods"
"/admin/enterprises/#{permalink}/edit#/payment_methods_panel"

View File

@@ -1,58 +0,0 @@
angular.module("admin.tagRules").controller "TagRulesCtrl", ($scope, $http, $filter, enterprise) ->
$scope.tagGroups = enterprise.tag_groups
$scope.defaultTagGroup = enterprise.default_tag_group
$scope.visibilityOptions = [ { id: "visible", name: t('js.tag_rules.visible') }, { id: "hidden", name: t('js.tag_rules.not_visible') } ]
$scope.updateRuleCounts = ->
index = $scope.defaultTagGroup.rules.length
for tagGroup in $filter('orderBy')($scope.tagGroups, 'position')
tagGroup.startIndex = index
index = index + tagGroup.rules.length
$scope.updateRuleCounts()
$scope.updateTagsRulesFor = (tagGroup) ->
for tagRule in tagGroup.rules
tagRule.preferred_customer_tags = (tag.text for tag in tagGroup.tags).join(",")
$scope.addNewRuleTo = (tagGroup, ruleType) ->
newRule =
id: null
is_default: tagGroup == $scope.defaultTagGroup
preferred_customer_tags: (tag.text for tag in tagGroup.tags).join(",")
type: "TagRule::#{ruleType}"
switch ruleType
when "FilterShippingMethods"
newRule.peferred_shipping_method_tags = []
newRule.preferred_matched_shipping_methods_visibility = "visible"
when "FilterPaymentMethods"
newRule.peferred_payment_method_tags = []
newRule.preferred_matched_payment_methods_visibility = "visible"
when "FilterProducts"
newRule.peferred_variant_tags = []
newRule.preferred_matched_variants_visibility = "visible"
when "FilterOrderCycles"
newRule.peferred_exchange_tags = []
newRule.preferred_matched_order_cycles_visibility = "visible"
tagGroup.rules.push(newRule)
$scope.updateRuleCounts()
$scope.addNewTag = ->
$scope.tagGroups.push { tags: [], rules: [], position: $scope.tagGroups.length + 1 }
$scope.deleteTagRule = (tagGroup, tagRule) ->
index = tagGroup.rules.indexOf(tagRule)
return unless index >= 0
if tagRule.id is null
tagGroup.rules.splice(index, 1)
$scope.updateRuleCounts()
else
if confirm("Are you sure?")
$http
method: "DELETE"
url: "/admin/enterprises/#{enterprise.id}/tag_rules/#{tagRule.id}.json"
.then ->
tagGroup.rules.splice(index, 1)
$scope.updateRuleCounts()
$scope.enterprise_form.$setDirty()

View File

@@ -1,11 +0,0 @@
angular.module("admin.tagRules").directive "invertNumber", ->
restrict: "A"
require: "ngModel"
link: (scope, element, attrs, ngModel) ->
ngModel.$parsers.push (viewValue) ->
return -parseInt(viewValue) unless isNaN(parseInt(viewValue))
viewValue
ngModel.$formatters.push (modelValue) ->
return -parseInt(modelValue) unless isNaN(parseInt(modelValue))
modelValue

View File

@@ -1,26 +0,0 @@
angular.module("admin.tagRules").directive 'newTagRuleDialog', ($rootScope, $compile, $templateCache, DialogDefaults, ruleTypes) ->
restrict: 'A'
scope:
tagGroup: '='
addNewRuleTo: '='
link: (scope, element, attr) ->
# Compile modal template
template = $compile($templateCache.get('admin/new_tag_rule_dialog.html'))(scope)
scope.ruleTypes = ruleTypes
scope.ruleType = scope.ruleTypes[0].id
# Set Dialog options
template.dialog(DialogDefaults)
# Link opening of dialog to click event on element
element.bind 'click', (e) ->
template.dialog('open')
$rootScope.$evalAsync()
scope.addRule = (tagGroup, ruleType) ->
scope.addNewRuleTo(tagGroup, ruleType)
template.dialog('close')
$rootScope.$evalAsync()
return

View File

@@ -1,41 +0,0 @@
angular.module("admin.tagRules").directive "tagRule", ->
restrict: "C"
templateUrl: "admin/tag_rules/tag_rule.html"
link: (scope, element, attrs) ->
scope.opt =
"TagRule::FilterShippingMethods":
textTop: t('js.admin.tag_rules.shipping_method_tagged_top')
textBottom: t('js.admin.tag_rules.shipping_method_tagged_bottom')
taggable: "shipping_method"
tagsAttr: "shipping_method_tags"
tagListAttr: "preferred_shipping_method_tags"
inputTemplate: "admin/tag_rules/filter_shipping_methods_input.html"
tagListFor: (rule) ->
rule.preferred_shipping_method_tags
"TagRule::FilterPaymentMethods":
textTop: t('js.admin.tag_rules.payment_method_tagged_top')
textBottom: t('js.admin.tag_rules.payment_method_tagged_bottom')
taggable: "payment_method"
tagsAttr: "payment_method_tags"
tagListAttr: "preferred_payment_method_tags"
inputTemplate: "admin/tag_rules/filter_payment_methods_input.html"
tagListFor: (rule) ->
rule.preferred_payment_method_tags
"TagRule::FilterOrderCycles":
textTop: t('js.admin.tag_rules.order_cycle_tagged_top')
textBottom: t('js.admin.tag_rules.order_cycle_tagged_bottom')
taggable: "exchange"
tagsAttr: "exchange_tags"
tagListAttr: "preferred_exchange_tags"
inputTemplate: "admin/tag_rules/filter_order_cycles_input.html"
tagListFor: (rule) ->
rule.preferred_exchange_tags
"TagRule::FilterProducts":
textTop: t('js.admin.tag_rules.inventory_tagged_top')
textBottom: t('js.admin.tag_rules.inventory_tagged_bottom')
taggable: "variant"
tagsAttr: "variant_tags"
tagListAttr: "preferred_variant_tags"
inputTemplate: "admin/tag_rules/filter_products_input.html"
tagListFor: (rule) ->
rule.preferred_variant_tags

View File

@@ -1,11 +0,0 @@
angular.module('Darkswarm').directive "darkerBackground", ->
restrict: "A"
link: (scope, elm, attr)->
toggleClass = (value) ->
elm.closest('.page-view').toggleClass("with-darker-background", value)
toggleClass(true)
# if an OrderCycle is selected, disable darker background
scope.$watch 'order_cycle.order_cycle_id', (newvalue, oldvalue) ->
toggleClass(false) if newvalue

View File

@@ -1,14 +0,0 @@
# Allows disabling of link buttons via disabled attribute.
# This is normally ignored, ie the link appears disabled but is still clickable.
angular.module('Darkswarm').directive "disableDynamically", ->
restrict: 'A'
link: (scope, element, attrs) ->
element.on 'click', (e) ->
if attrs.disabled
e.preventDefault()
return
scope.$on "$destroy", ->
element.off("click")

View File

@@ -1,7 +0,0 @@
angular.module('Darkswarm').directive "ofnInlineAlert", ->
restrict: 'A'
scope: true
link: (scope, elem, attrs) ->
scope.visible = true
scope.close = ->
scope.visible = false

View File

@@ -1,21 +0,0 @@
angular.module('Darkswarm').directive "ofnPageAlert", ($timeout) ->
restrict: 'A'
scope: true
link: (scope, elem, attrs) ->
moveSelectors = [".off-canvas-wrap .inner-wrap",
".off-canvas-wrap .inner-wrap .fixed",
".off-canvas-fixed .top-bar",
".off-canvas-fixed ofn-flash",
".off-canvas-fixed nav.tab-bar",
".off-canvas-fixed .page-alert"]
container_elems = $(moveSelectors.join(", "))
# Wait a moment after page load before showing the alert. Otherwise we often miss the
# start of the animation.
$timeout ->
container_elems.addClass("move-up")
, 1000
scope.close = ->
container_elems.removeClass("move-up")

View File

@@ -1,10 +0,0 @@
#new-tag-rule-dialog
.text-normal.margin-bottom-30.text-center
{{ 'js.admin.new_tag_rule_dialog.select_rule_type' | t }}
.text-center.margin-bottom-30
-# %select.fullwidth{ 'select2-min-search' => 5, 'ng-model' => 'newRuleType', 'ng-options' => 'ruleType.id as ruleType.name for ruleType in availableRuleTypes' }
%input.ofn-select2.fullwidth{ id: 'rule_type_selector', data: "ruleTypes", "min-search": "5", "ng-model": "ruleType" }
.text-center
%input.button.red.icon-plus{ type: 'button', value: "{{ 'js.admin.new_tag_rule_dialog.add_rule' | t }}", "ng-click": 'addRule(tagGroup, ruleType)' }

View File

@@ -3,4 +3,4 @@
%span.text-normal
{{ 'admin.tags' | t }}
%br
%tags-with-translation.fullwidth{ object: 'object' }
%tags-with-translation.fullwidth{ object: 'object', form: 'order_cycle_form', id: 'tags_with_translation'}

View File

@@ -1,3 +0,0 @@
%div
%input{ type: "number", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_calculator_attributes_preferred_flat_percent", min: -100, max: 100, "invert-number": true, "ng-model": "rule.calculator.preferred_flat_percent" }
%span.text-normal %

View File

@@ -1,5 +0,0 @@
%div
%input.fullwidth.light.ofn-select2{ id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_order_cycles_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_order_cycles_visibility]", data: 'visibilityOptions', "min-search": 5, "ng-model": "rule.preferred_matched_order_cycles_visibility", "ng-if": "!rule.is_default" }
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_order_cycles_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_order_cycles_visibility]", "ng-value": "'hidden'", "ng-if": "rule.is_default" }
%span.text-normal{ "ng-if": "rule.is_default" }
=t(:not_visible)

View File

@@ -1,5 +0,0 @@
%div
%input.fullwidth.light.ofn-select2{ id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_payment_methods_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_payment_methods_visibility]", data: 'visibilityOptions', "min-search": 5, "ng-model": "rule.preferred_matched_payment_methods_visibility", "ng-if": "!rule.is_default" }
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_payment_methods_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_payment_methods_visibility]", "ng-value": "'hidden'", "ng-if": "rule.is_default" }
%span.text-normal{ "ng-if": "rule.is_default" }
= t(:not_visible)

View File

@@ -1,5 +0,0 @@
%div
%input.fullwidth.light.ofn-select2{ id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_variants_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_variants_visibility]", data: 'visibilityOptions', "min-search": 5, "ng-model": "rule.preferred_matched_variants_visibility", "ng-if": "!rule.is_default" }
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_variants_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_variants_visibility]", "ng-value": "'hidden'", "ng-if": "rule.is_default" }
%span.text-normal{ "ng-if": "rule.is_default" }
= t(:not_visible)

View File

@@ -1,6 +0,0 @@
%div
%input.fullwidth.light.ofn-select2{ id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_shipping_methods_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_shipping_methods_visibility]", data: 'visibilityOptions', "min-search": 5, "ng-model": "rule.preferred_matched_shipping_methods_visibility", "ng-if": "!rule.is_default" }
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_shipping_methods_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_shipping_methods_visibility]", "ng-value": "'hidden'", "ng-if": "rule.is_default" }
%span.text-normal{ "ng-if": "rule.is_default" }
= t(:not_visible)

View File

@@ -1,32 +0,0 @@
%div{ id: "tr_{{tagGroup.startIndex + $index}}" }
%table
%colgroup
%col.text{ width: "35%" }
%col.inputs{ width: "55%" }
%col.actions{ width: "10%" }
%tr
%td
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_id", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][id]", "ng-value": "rule.id" }
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_type", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][type]", "ng-value": "rule.type" }
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_priority", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][priority]", "ng-value": "tagGroup.startIndex + $index" }
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_is_default", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][is_default]", "ng-value": "rule.is_default" }
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_customer_tags", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_customer_tags]", "ng-value": "rule.preferred_customer_tags" }
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_{{opt[rule.type].taggable}}_tags", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_{{opt[rule.type].taggable}}_tags]", "ng-value": "opt[rule.type].tagListFor(rule)" }
%span.text-normal {{ opt[rule.type].textTop }}
%td
%tags-with-translation{ object: "rule", max: 1, "tags-attr" => "{{opt[rule.type].tagsAttr}}", "tag-list-attr" => "{{opt[rule.type].tagListAttr}}" }
%td.actions{ rowspan: 2 }
%a{ class: "delete-tag-rule icon-trash no-text", "ng-click": "deleteTagRule(tagGroup || defaultTagGroup, rule)" }
%tr
%td
%span.text-normal {{ opt[rule.type].textBottom }}
%td
%div{ "ng-include": "opt[rule.type].inputTemplate" }
%hr

View File

@@ -0,0 +1,21 @@
# frozen_string_literal: true
class AddTagRuleModalComponent < ModalComponent
def initialize(id:, tag_rule_types:, current_index:, div_id:, is_default: false,
customer_tag: "", hidden_field_customer_tag_options: {} )
super
@close_button = false
@modal_class = "tiny"
@tag_rule_types = tag_rule_types
@current_index = current_index
@div_id = div_id
@is_default = is_default
@customer_tag = customer_tag
@hidden_field_customer_tag_options = hidden_field_customer_tag_options
end
attr_reader :tag_rule_types, :current_index, :div_id, :is_default, :customer_tag,
:hidden_field_customer_tag_options
end

View File

@@ -0,0 +1,32 @@
-# as far as I can tell we can't pass content to the parent template while rendering ie: something like :
-# = render_parent do
-# .something
-# my content
-# Workarount is to copy the ModalComponent template
%div{ id: @id, "data-controller": @data_controller, "data-action": @data_action, "data-modal-instant-value": @instant, **@options }
.reveal-modal-bg.fade{ "data-modal-target": "background", "data-action": "click->modal#close" }
.reveal-modal.fade.modal-component{ "data-modal-target": "modal", class: @modal_class }
#new-tag-rule-dialog{ "data-controller": "add-tag-rule-modal",
"data-add-tag-rule-modal-index-value": current_index }
-# Ideally we would use event to communicate the update of customer tag, but we would need
-# the element with "data-controller": "add-tag-rule-modal"
-# to be parent of the element with "data-controller": "tag-rule-group-form"
-# so it could respond to event generated by "tag-rule-group-form".
-# Here we are in the opposite situation so we use a hidden field to store the value of
-# the customer tag, so it can be updated by "tag-rule-group-form"
= hidden_field_tag "customer_tag", customer_tag, { "data-add-tag-rule-modal-target": "ruleCustomerTag" }.merge(hidden_field_customer_tag_options)
.text-normal.margin-bottom-30.text-center
= t('components.add_tag_rule_modal.select_rule_type')
.text-center.margin-bottom-30
= select_tag :rule_type_selector, options_for_select(tag_rule_types), { "data-controller": "tom-select", "data-add-tag-rule-modal-target": "rule", class: "primary no-search" }
.text-center
%input.button.red.icon-plus{ type: 'button',
value: "#{t('components.add_tag_rule_modal.add_rule')}",
"data-action": "click->add-tag-rule-modal#add click->modal#close",
"data-add-tag-rule-modal-div-id-param": div_id,
"data-add-tag-rule-modal-is-default-param": "#{is_default}"}
- if close_button?
.text-center
%input{ class: "button icon-plus #{close_button_class}", type: 'button', value: t('js.admin.modals.close'), "data-action": "click->modal#close" }

View File

@@ -0,0 +1,46 @@
import { Controller } from "stimulus";
import showHttpError from "../../webpacker/js/services/show_http_error";
export default class extends Controller {
static targets = ["rule", "ruleCustomerTag"];
static values = { index: Number };
add({ params }) {
const rule_type = this.ruleTarget.value;
const index = this.indexValue;
const divId = params["divId"];
const isDefault = params["isDefault"];
const customerTags = this.hasRuleCustomerTagTarget
? this.ruleCustomerTagTarget.value
: undefined;
const urlParams = new URLSearchParams();
urlParams.append("rule_type", rule_type);
urlParams.append("index", index);
urlParams.append("div_id", divId);
urlParams.append("is_default", isDefault);
if (customerTags != undefined) {
urlParams.append("customer_tags", customerTags);
}
// fetch from backend
fetch(`tag_rules/new?${urlParams}`, {
method: "GET",
headers: {
Accept: "text/vnd.turbo-stream.html",
},
})
.then((response) => {
if (!response.ok) {
showHttpError(response.status);
throw response;
}
return response.text();
})
.then((html) => {
Turbo.renderStreamMessage(html);
this.indexValue = parseInt(index) + 1;
})
.catch((error) => console.error(error));
}
}

View File

@@ -1,4 +1,5 @@
// This controller will be called "example-component--example", ie "component-subdirectory--js-file-name"
// This controller will be called "example", ie "js-file-name" minus the "_controller.js"
// see controller/index.js for more info
import { Controller } from "stimulus";
export default class extends Controller {}

View File

@@ -1,16 +1,26 @@
# frozen_string_literal: true
class TagListInputComponent < ViewComponent::Base
# method in a "hidden_field" form helper and is the method used to get a list of tag on the model
def initialize(form:, method:, tags:,
def initialize(name:, tags:,
placeholder: I18n.t("components.tag_list_input.default_placeholder"),
aria_label: nil)
@f = form
@method = method
only_one: false,
aria_label: nil,
hidden_field_data_options: {})
@name = name
@tags = tags
@placeholder = placeholder
@only_one = only_one
@aria_label_option = aria_label ? { 'aria-label': aria_label } : {}
@hidden_field_data_options = hidden_field_data_options
end
attr_reader :f, :method, :tags, :placeholder, :aria_label_option
attr_reader :name, :tags, :placeholder, :only_one, :aria_label_option, :hidden_field_data_options
private
def display
return "none" if tags.length >= 1 && only_one == true
"block"
end
end

View File

@@ -1,19 +1,19 @@
%div{ "data-controller": "tag-list-input-component--tag-list-input" }
%div{ "data-controller": "tag-list-input", "data-tag-list-input-only-one-value": "#{only_one}" }
.tags-input
.tags
- # We use display:none instead of hidden field, so changes to the value can be picked up by the bulkFormController
= f.text_field method.to_sym, value: tags.join(","), "data-tag-list-input-component--tag-list-input-target": "tagList", "style": "display: none"
%ul.tag-list{"data-tag-list-input-component--tag-list-input-target": "list"}
%template{"data-tag-list-input-component--tag-list-input-target": "template"}
= text_field_tag name, tags.join(","), {"data-tag-list-input-target": "tagList", "style": "display: none"}.merge(hidden_field_data_options)
%ul.tag-list{"data-tag-list-input-target": "list"}
%template{"data-tag-list-input-target": "template"}
%li.tag-item
.tag-template
%span
%a.remove-button{ "data-action": "click->tag-list-input-component--tag-list-input#removeTag" }
%a.remove-button{ "data-action": "click->tag-list-input#removeTag" }
×
- tags.each do |tag|
%li.tag-item
.tag-template
%span=tag
%a.remove-button{ "data-action": "click->tag-list-input-component--tag-list-input#removeTag" }
%a.remove-button{ "data-action": "click->tag-list-input#removeTag" }
×
= text_field_tag "variant_add_tag_#{f.object.id}".to_sym, nil, class: "input", placeholder: placeholder, "data-action": "keydown.enter->tag-list-input-component--tag-list-input#addTag keyup->tag-list-input-component--tag-list-input#filterInput", "data-tag-list-input-component--tag-list-input-target": "newTag", **aria_label_option
= text_field_tag "variant_add_tag", nil, class: "input", placeholder: placeholder, "data-action": "keydown.enter->tag-list-input#addTag keyup->tag-list-input#filterInput blur->tag-list-input#addTag", "data-tag-list-input-target": "newTag", **aria_label_option, style: "display: #{display};"

View File

@@ -2,17 +2,18 @@ import { Controller } from "stimulus";
export default class extends Controller {
static targets = ["tagList", "newTag", "template", "list"];
static values = { onlyOne: Boolean };
addTag(event) {
// prevent hotkey form submitting the form (default action for "enter" key)
event.preventDefault();
// Check if tag already exist
const newTagName = this.newTagTarget.value.trim();
const newTagName = this.newTagTarget.value.trim().replaceAll(" ", "-");
if (newTagName.length == 0) {
return;
}
// Check if tag already exist
const tags = this.tagListTarget.value.split(",");
const index = tags.indexOf(newTagName);
if (index != -1) {
@@ -22,7 +23,13 @@ export default class extends Controller {
}
// add to tagList
this.tagListTarget.value = this.tagListTarget.value.concat(`,${newTagName}`);
if (this.tagListTarget.value == "") {
this.tagListTarget.value = newTagName;
} else {
this.tagListTarget.value = this.tagListTarget.value.concat(`,${newTagName}`);
}
// manualy dispatch an Input event so the change can get picked up by other controllers
this.tagListTarget.dispatchEvent(new InputEvent("input"));
// Create new li component with value
const newTagElement = this.templateTarget.content.cloneNode(true);
@@ -32,6 +39,11 @@ export default class extends Controller {
// Clear new tag value
this.newTagTarget.value = "";
// hide tag input if limited to one tag
if (this.tagListTarget.value.split(",").length == 1 && this.onlyOneValue == true) {
this.newTagTarget.style.display = "none";
}
}
removeTag(event) {
@@ -40,13 +52,18 @@ export default class extends Controller {
// Remove tag from list
const tags = this.tagListTarget.value.split(",");
this.tagListTarget.value = tags.filter(tag => tag != tagName).join(",");
this.tagListTarget.value = tags.filter((tag) => tag != tagName).join(",");
// manualy dispatch an Input event so the change gets picked up by the bulk form controller
this.tagListTarget.dispatchEvent(new InputEvent("input"));
// Remove HTML element from the list
event.srcElement.parentElement.parentElement.remove();
// Make sure the tag input is displayed
if (this.tagListTarget.value.length == 0) {
this.newTagTarget.style.display = "block";
}
}
filterInput(event) {

View File

@@ -0,0 +1,59 @@
# frozen_string_literal: true
class TagRuleFormComponent < ViewComponent::Base
def initialize(rule:, index:, customer_tags: "",
hidden_field_customer_tag_options: {})
@rule = rule
@index = index
@customer_tags = customer_tags
@hidden_field_customer_tag_options = hidden_field_customer_tag_options
end
attr_reader :rule, :index, :customer_tags, :hidden_field_customer_tag_options
private
def element_name(name)
"enterprise[tag_rules_attributes][#{index}][#{name}]"
end
def rule_data # rubocop:disable Metrics/MethodLength
case rule.type
when "TagRule::FilterShippingMethods"
{
text_top: t('components.tag_rule_form.tag_rules.shipping_method_tagged_top'),
text_bottom: t('components.tag_rule_form.tag_rules.shipping_method_tagged_bottom'),
taggable: "shipping_method",
visibility_field: "preferred_matched_shipping_methods_visibility",
}
when "TagRule::FilterPaymentMethods"
{
text_top: t('components.tag_rule_form.tag_rules.payment_method_tagged_top'),
text_bottom: t('components.tag_rule_form.tag_rules.payment_method_tagged_bottom'),
taggable: "payment_method",
visibility_field: "preferred_matched_payment_methods_visibility",
}
when "TagRule::FilterOrderCycles"
{
text_top: t('components.tag_rule_form.tag_rules.order_cycle_tagged_top'),
text_bottom: t('components.tag_rule_form.tag_rules.order_cycle_tagged_bottom'),
taggable: "exchange",
visibility_field: "preferred_matched_order_cycles_visibility",
}
when "TagRule::FilterProducts"
{
text_top: t('components.tag_rule_form.tag_rules.inventory_tagged_top'),
text_bottom: t('components.tag_rule_form.tag_rules.inventory_tagged_bottom'),
taggable: "variant",
visibility_field: "preferred_matched_variants_visibility",
}
end
end
def visibility_options
[
[t('components.tag_rule_form.tag_rules.visible'), "visible"],
[t('components.tag_rule_form.tag_rules.not_visible'), "hidden"]
]
end
end

View File

@@ -0,0 +1,35 @@
%div{ id: "tr_#{index}" }
%table
%colgroup
%col.text{ width: "35%" }
%col.inputs{ width: "55%" }
%col.actions{ width: "10%" }
%tr
%td
= hidden_field_tag element_name("id"), rule.id
= hidden_field_tag element_name("type"), rule.type
= hidden_field_tag element_name("priority"), index
= hidden_field_tag element_name("is_default"), rule.is_default
= hidden_field_tag element_name("preferred_customer_tags"), customer_tags, hidden_field_customer_tag_options
%span.text-normal
= rule_data[:text_top]
%td
= render TagListInputComponent.new(name: element_name("preferred_#{rule_data[:taggable]}_tags"), tags: rule.tags.split(","), only_one: true)
%td.actions{ rowspan: 2 , "data-controller": "delete-tag-rule", "data-delete-tag-rule-index-value": index }
- if rule.new_record?
= link_to("", "#", { "data-action": "click->delete-tag-rule#delete" ,class: "delete-tag-rule icon-trash no-text"})
- else
= link_to("", "#{admin_enterprise_tag_rule_url(rule.enterprise_id, rule.id)}?index=#{index}", { "data-turbo-method": "delete", "data-turbo-confirm": t("admin.tag_rules.confirm_delete"), class: "delete-tag-rule icon-trash no-text" })
%tr
%td
%span.text-normal
= rule_data[:text_bottom]
%td
%div
%div
- if rule.is_default
= hidden_field_tag "enterprise[tag_rules_attributes][#{index}][#{rule_data[:visibility_field]}]", "hidden"
%span.text-normal
= t(:not_visible)
- else
= select_tag "enterprise[tag_rules_attributes][#{index}][#{rule_data[:visibility_field]}]", options_for_select(visibility_options, rule.public_send(rule_data[:visibility_field].to_sym) ), { "data-controller": "tom-select", class: "primary no-search" }

View File

@@ -0,0 +1,26 @@
# frozen_string_literal: true
class TagRuleGroupFormComponent < ViewComponent::Base
def initialize(group:, index:, customer_rule_index:, tag_rule_types:)
@group = group
@index = index
@customer_rule_index = customer_rule_index
@tag_rule_types = tag_rule_types
end
attr_reader :group, :index, :customer_rule_index, :tag_rule_types
private
def form_id
"tg_#{index}"
end
def customer_tag_rule_div_id
"new-customer-tag-rule-#{index}"
end
def tag_list_input_name
"group[#{index}][preferred_customer_tags]"
end
end

View File

@@ -0,0 +1,39 @@
%div{ id: form_id, "data-controller": "tag-rule-group-form" }
- rule_index = customer_rule_index
.customer_tag
.header
%table
%colgroup
%col{width: '35%'}
%col{width: '65%'}
%tr
%td
%h5
= t('components.tag_rule_group_form.for_customers_tagged')
%td
= render(TagListInputComponent.new(name: tag_list_input_name,
tags: group[:tags],
only_one: true,
hidden_field_data_options: { "data-action": "input->tag-rule-group-form#updatePreferredCustomerTag", "data-tag-rule-group-form-target": "customerTag" }))
%div{ id: customer_tag_rule_div_id }
- if group[:rules].empty?
.no_rules
= t('components.tag_rule_group_form.no_rules_yet')
- else
- group[:rules].each do |rule|
- rule_index += 1
= render(TagRuleFormComponent.new(rule: rule,
index: rule_index,
customer_tags: group[:tags],
hidden_field_customer_tag_options: { "data-tag-rule-group-form-target": "ruleCustomerTag" }))
%hr
.add_rule.text-center
%input.button{ type: 'button', value: t('components.tag_rule_group_form.add_new_rule'), "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "tag_rule_add_new_rule_#{index}" }
= render AddTagRuleModalComponent.new(id: "tag_rule_add_new_rule_#{index}",
tag_rule_types: tag_rule_types,
current_index: (rule_index + 1),
div_id: customer_tag_rule_div_id,
customer_tag: group[:tags],
hidden_field_customer_tag_options: { "data-tag-rule-group-form-target": "ruleCustomerTag" })

View File

@@ -0,0 +1,11 @@
import { Controller } from "stimulus";
export default class extends Controller {
static targets = ["customerTag", "ruleCustomerTag"];
updatePreferredCustomerTag() {
const customerTag = this.customerTagTarget.value;
this.ruleCustomerTagTargets.forEach((element) => (element.value = customerTag));
}
}

View File

@@ -1,6 +0,0 @@
# frozen_string_literal: true
module VerticalEllipsisMenu
class Component < ViewComponent::Base
end
end

View File

@@ -0,0 +1,4 @@
# frozen_string_literal: true
class VerticalEllipsisMenuComponent < ViewComponent::Base
end

View File

@@ -1,4 +1,4 @@
.vertical-ellipsis-menu{ "data-controller": "vertical-ellipsis-menu--component" }
%i.fa.fa-ellipsis-v{ "data-action": "click->vertical-ellipsis-menu--component#toggle" }
.vertical-ellipsis-menu-content{ "data-vertical-ellipsis-menu--component-target": "content" }
.vertical-ellipsis-menu{ "data-controller": "vertical-ellipsis-menu" }
%i.fa.fa-ellipsis-v{ "data-action": "click->vertical-ellipsis-menu#toggle" }
.vertical-ellipsis-menu-content{ "data-vertical-ellipsis-menu-target": "content" }
= content

View File

@@ -83,6 +83,7 @@ module Admin
format.turbo_stream
end
else
load_tag_rule_types
respond_with(@object) do |format|
format.json {
render json: { errors: @object.errors.messages }, status: :unprocessable_entity
@@ -147,6 +148,18 @@ module Admin
end
end
def new_tag_rule_group
load_tag_rule_types
@index = params[:index]
@customer_rule_index = params[:customer_rule_index].to_i
@group = { tags: [], rules: [] }
respond_to do |format|
format.turbo_stream
end
end
protected
def delete_custom_tab
@@ -379,16 +392,15 @@ module Admin
end
def load_tag_rule_types
# Load rule types
@tag_rule_types = [
{ id: "FilterShippingMethods", name: t('js.tag_rules.show_hide_shipping') },
{ id: "FilterPaymentMethods", name: t('js.tag_rules.show_hide_payment') },
{ id: "FilterOrderCycles", name: t('js.tag_rules.show_hide_order_cycles') }
[t(".form.tag_rules.show_hide_shipping"), "FilterShippingMethods"],
[t(".form.tag_rules.show_hide_payment"), "FilterPaymentMethods"],
[t(".form.tag_rules.show_hide_order_cycles"), "FilterOrderCycles"]
]
return unless helpers.feature?(:inventory, @object)
@tag_rule_types.prepend({ id: "FilterProducts", name: t('js.tag_rules.show_hide_variants') })
@tag_rule_types.prepend([t(".form.tag_rules.show_hide_variants"), "FilterProducts"])
end
def setup_property

View File

@@ -49,7 +49,7 @@ module Admin
errors: @importer.errors.full_messages
}
if helpers.feature?(:inventory, spree_current_user.enterprises)
if helpers.feature?(:inventory, *spree_current_user.enterprises)
json[:results][:inventory_created] = @importer.inventory_created_count
json[:results][:inventory_updated] = @importer.inventory_updated_count
end
@@ -175,7 +175,7 @@ module Admin
# Return an error if trying to import into inventories when inventory is disable
def can_import_into_inventories?
return true if helpers.feature?(:inventory, spree_current_user.enterprises) ||
return true if helpers.feature?(:inventory, *spree_current_user.enterprises) ||
params.dig(:settings, "import_into") != 'inventories'
redirect_to admin_product_import_url, notice: I18n.t(:product_import_inventory_disable)

View File

@@ -123,6 +123,13 @@ module Admin
@page = params[:page].presence || 1
@per_page = params[:per_page].presence || 15
@q = params.permit(q: {})[:q] || { s: 'name asc' }
# Transform on_hand sorting to include backorderable_priority (on-demand) for proper ordering
if @q[:s] == 'on_hand asc'
@q[:s] = ['backorderable_priority asc', @q[:s]]
elsif @q[:s] == 'on_hand desc'
@q[:s] = ['backorderable_priority desc', @q[:s]]
end
end
def producers
@@ -155,8 +162,27 @@ module Admin
product_query = OpenFoodNetwork::Permissions.new(spree_current_user)
.editable_products.merge(product_scope_with_includes).ransack(ransack_query).result
@pagy, @products = pagy(product_query.order(:name), limit: @per_page, page: @page,
size: [1, 2, 2, 1])
# Postgres requires ORDER BY expressions to appear in the SELECT list when using DISTINCT.
# When the current ransack sort uses the computed stock columns, include them in the select
# so the generated COUNT/DISTINCT query is valid.
sort_columns = Array(@q && @q[:s]).flatten
if sort_columns.any? { |s|
s.to_s.include?('on_hand') || s.to_s.include?('backorderable_priority')
}
product_query = product_query.select(
Arel.sql('spree_products.*'),
Spree::Product.backorderable_priority_sql,
Spree::Product.on_hand_sql
)
end
@pagy, @products = pagy(
product_query.order(:name),
limit: @per_page,
page: @page,
size: [1, 2, 2, 1]
)
end
def product_scope

View File

@@ -22,14 +22,12 @@ module Admin
def show
@report = report_class.new(spree_current_user, params, render: false)
@rendering_options = rendering_options
show_report
end
def create
@report = report_class.new(spree_current_user, params, render: true)
update_rendering_options
render_in_background
end
@@ -61,7 +59,9 @@ module Admin
@blob = ReportBlob.create_for_upload_later!(report_filename)
ReportJob.perform_later(
report_class:, user: spree_current_user, params:,
report_class:,
user: spree_current_user,
params:,
format: report_format,
blob: @blob,
channel: ScopedChannel.for_id(params[:uuid]),

View File

@@ -1,12 +1,45 @@
# frozen_string_literal: true
module Admin
class TagRulesController < Admin::ResourceController
class TagRulesController < Spree::Admin::BaseController
respond_to :json
respond_override destroy: { json: {
success: lambda { head :no_content }
} }
def new
@index = params[:index]
@div_id = params[:div_id]
is_default = params[:is_default]
@customer_tags = params[:customer_tags]
status = :ok
if permitted_tag_rule_type.include?(params[:rule_type])
@default_rule = "TagRule::#{params[:rule_type]}".constantize.new(is_default:)
else
flash.now[:error] = t(".not_supported_type")
status = :internal_server_error
end
respond_with do |format|
format.turbo_stream { render :new, status: }
end
end
def destroy
@rule = TagRule.find(params[:id])
@index = params[:index]
authorize! :destroy, @rule
status = :ok
if @rule.destroy
flash[:success] = Spree.t(:successfully_removed, resource: "Tag Rule")
else
flash.now[:error] = t(".destroy_error")
status = :internal_server_error
end
respond_to do |format|
format.turbo_stream { render :destroy, status: }
end
end
def map_by_tag
respond_to do |format|
@@ -39,5 +72,13 @@ module Admin
Enterprise.managed_by(spree_current_user)
end
end
def model_class
TagRule
end
def permitted_tag_rule_type
%w{FilterOrderCycles FilterPaymentMethods FilterProducts FilterShippingMethods}
end
end
end

View File

@@ -80,8 +80,6 @@ class CheckoutController < BaseController
@order.customer.touch :terms_and_conditions_accepted_at
return true if redirect_to_payment_gateway
# Redeem VINE voucher
vine_voucher_redeemer = Vine::VoucherRedeemerService.new(order: @order)
unless vine_voucher_redeemer.redeem
@@ -94,6 +92,9 @@ class CheckoutController < BaseController
return false
# rubocop:enable Rails/DeprecatedActiveModelErrorsMethods
end
return true if redirect_to_payment_gateway
@order.process_payments!
@order.confirm!
BackorderJob.check_stock(@order)

View File

@@ -84,6 +84,7 @@ module ReportsActions
else
params[:fields_to_show]
end,
display_metadata_rows: false,
display_summary_row: request.get?,
display_header_row: false
}
@@ -94,6 +95,7 @@ module ReportsActions
rendering_options.update(
options: {
fields_to_show: params[:fields_to_show],
display_metadata_rows: params[:display_metadata_rows].present?,
display_summary_row: params[:display_summary_row].present?,
display_header_row: params[:display_header_row].present?
}

View File

@@ -9,11 +9,7 @@ class PaymentsController < BaseController
@payment = Spree::Payment.find(params[:id])
authorize! :show, @payment.order
if (url = @payment.cvv_response_message)
redirect_to url
else
redirect_to order_url(@payment.order)
end
redirect_to(@payment.redirect_auth_url || order_url(@payment.order))
end
private

View File

@@ -0,0 +1,13 @@
# frozen_string_literal: true
class WellKnownController < ApplicationController
layout nil
def dfc
base = "https://github.com/datafoodconsortium/taxonomies/releases/latest/download/scopes.rdf#"
render json: {
"#{base}ReadEnterprise" => "/api/dfc/enterprises/",
"#{base}ReadProducts" => "/api/dfc/supplied_products/",
}
end
end

View File

@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Admin
module EnterprisesHelper
module EnterprisesHelper # rubocop:disable Metrics/ModuleLength
def add_check_if_single(count)
if count == 1
{ checked: true }
@@ -26,9 +26,9 @@ module Admin
show_enterprise_fees = can?(:manage_enterprise_fees,
enterprise) && (is_shop || enterprise.is_primary_producer)
show_connected_apps = can?(:manage_connected_apps, enterprise) &&
feature?(:connected_apps, spree_current_user, enterprise) &&
Spree::Config.connected_apps_enabled.present?
show_inventory_settings = feature?(:inventory, spree_current_user.enterprises) && is_shop
(connected_apps_enabled(enterprise).present? ||
dfc_platforms_available?)
show_inventory_settings = feature?(:inventory, *spree_current_user.enterprises) && is_shop
show_options = {
show_properties:,
@@ -42,11 +42,19 @@ module Admin
build_enterprise_side_menu_items(is_shop:, show_options:)
end
def connected_apps_enabled
def connected_apps_enabled(enterprise)
return [] unless feature?(:connected_apps, spree_current_user, enterprise)
connected_apps_enabled = Spree::Config.connected_apps_enabled&.split(',') || []
ConnectedApp::TYPES & connected_apps_enabled
end
def dfc_platforms_available?
ApiUser::PLATFORMS.keys.any? do |id|
feature?(id, spree_current_user)
end
end
def enterprise_attachment_removal_modal_id
attachment_removal_parameter # remove_logo|remove_promo_image|remove_white_label_logo
end
@@ -63,8 +71,35 @@ module Admin
"#{enterprise_attachment_removal_panel}_panel"
end
def enterprise_sells_options
scope = "admin.enterprises.admin_index.sells_options"
Enterprise::SELLS.map { |s| [I18n.t(s, scope:), s] }
end
# Group tag rules per rule.preferred_customer_tags
def tag_groups(tag_rules)
tag_rules.each_with_object([]) do |tag_rule, tag_groups|
tag_group = find_match(tag_groups, tag_rule.preferred_customer_tags.split(","))
if tag_group[:rules].blank?
tag_groups << tag_group
tag_group[:position] = tag_groups.count
end
tag_group[:rules] << tag_rule
end
end
private
def find_match(tag_groups, tags)
tag_groups.each do |tag_group|
return tag_group if tag_group[:tags].length == tags.length &&
(tag_group[:tags] & tags) == tag_group[:tags]
end
{ tags:, rules: [] }
end
def build_enterprise_side_menu_items(is_shop:, show_options: ) # rubocop:disable Metrics/MethodLength
[
{ name: 'primary_details', icon_class: "icon-home", show: true, selected: 'selected' },

View File

@@ -1,6 +1,29 @@
# frozen_string_literal: true
module LinkHelper
def link_to_or_disabled(name = nil, options = nil, html_options = nil, &block)
html_options, options, name = options, name, block if block_given?
html_options ||= {}
if !!html_options.delete(:disabled)
# https://www.scottohara.me/blog/2021/05/28/disabled-links.html
html_options.merge!(
'aria-disabled': true,
class: (html_options[:class].to_s.split + ["disabled"]).uniq.join(" "),
role: "link"
)
if block_given?
content_tag("a", name, **html_options, &block)
else
content_tag("a", name, **html_options)
end
elsif block_given?
link_to options, html_options, &block
else
link_to name, options, html_options
end
end
def link_to_service(baseurl, name, html_options = {}, &)
return if name.blank?

View File

@@ -62,6 +62,12 @@ module ShopHelper
true
end
def shop_tab_class(tab)
return unless (tab == "home" && show_home_tab?) || current_order(false)&.order_cycle.nil?
"with-darker-background"
end
private
def show_groups_tabs?

View File

@@ -9,6 +9,7 @@ class ApplicationRecord < ActiveRecord::Base
include ArelHelpers::JoinAssociation
self.abstract_class = true
self.include_root_in_json = true
def self.image_service
ENV["S3_BUCKET"].present? ? :amazon_public : :local

View File

@@ -0,0 +1,35 @@
# frozen_string_literal: true
module ProductSortByStocks
extend ActiveSupport::Concern
included do
@on_hand_sql = Arel.sql("(
SELECT COALESCE(SUM(si.count_on_hand), 0)
FROM spree_variants v
JOIN spree_stock_items si ON si.variant_id = v.id
WHERE v.product_id = spree_products.id
GROUP BY v.product_id
)")
@backorderable_priority_sql = Arel.sql("(
SELECT BOOL_OR(si.backorderable)
FROM spree_variants v
JOIN spree_stock_items si ON si.variant_id = v.id
WHERE v.product_id = spree_products.id
GROUP BY v.product_id
)")
class << self
attr_reader :on_hand_sql, :backorderable_priority_sql
end
ransacker :on_hand do
@on_hand_sql
end
ransacker :backorderable_priority do
@backorderable_priority_sql
end
end
end

View File

@@ -0,0 +1,15 @@
# frozen_string_literal: true
# Authorisations of a user allowing a platform to access to data.
class DfcPermission < ApplicationRecord
SCOPES = %w[
ReadEnterprise ReadProducts ReadOrders
WriteEnterprise WriteProducts WriteOrders
].freeze
belongs_to :user, class_name: "Spree::User"
belongs_to :enterprise
validates :grantee, presence: true
validates :scope, presence: true, inclusion: { in: SCOPES }
end

View File

@@ -75,6 +75,7 @@ class Enterprise < ApplicationRecord
has_one :stripe_account, dependent: :destroy
has_many :vouchers, dependent: :restrict_with_exception
has_many :connected_apps, dependent: :destroy
has_many :dfc_permissions, dependent: :destroy
has_one :custom_tab, dependent: :destroy
delegate :latitude, :longitude, :city, :state_name, to: :address

View File

@@ -193,7 +193,7 @@ module ProductImport
order('is_primary_producer ASC, name').
map { |e| @editable_enterprises[e.name] = e.id }
return unless OpenFoodNetwork::FeatureToggle.enabled?(:inventory, @current_user.enterprises)
return unless OpenFoodNetwork::FeatureToggle.enabled?(:inventory, *@current_user.enterprises)
@inventory_permissions = permissions.variant_override_enterprises_per_hub
end

View File

@@ -142,6 +142,7 @@ module Spree
can [:admin, :index, :read, :create, :edit, :update_positions, :destroy], ProducerProperty
can :new, TagRule
can [:admin, :map_by_tag, :destroy], TagRule do |tag_rule|
user.enterprises.include? tag_rule.enterprise
end
@@ -149,7 +150,7 @@ module Spree
can [:admin, :index, :create], Enterprise
can [:read, :edit, :update,
:remove_logo, :remove_promo_image, :remove_terms_and_conditions,
:bulk_update, :resend_confirmation], Enterprise do |enterprise|
:bulk_update, :resend_confirmation, :new_tag_rule_group], Enterprise do |enterprise|
OpenFoodNetwork::Permissions.new(user).editable_enterprises.include? enterprise
end
can [:welcome, :register], Enterprise do |enterprise|
@@ -213,7 +214,7 @@ module Spree
managed_product_enterprises.include? variant.supplier
end
if OpenFoodNetwork::FeatureToggle.enabled?(:inventory, user.enterprises)
if OpenFoodNetwork::FeatureToggle.enabled?(:inventory, *user.enterprises)
can [:admin, :index, :read, :update, :bulk_update, :bulk_reset], VariantOverride do |vo|
next false unless vo.hub.present? && vo.variant&.supplier.present?

View File

@@ -57,7 +57,7 @@ module Spree
scope :failed, -> { with_state('failed') }
scope :valid, -> { where.not(state: %w(failed invalid)) }
scope :void, -> { with_state('void') }
scope :authorization_action_required, -> { where.not(cvv_response_message: nil) }
scope :authorization_action_required, -> { where.not(redirect_auth_url: nil) }
scope :requires_authorization, -> { with_state("requires_authorization") }
scope :with_payment_intent, ->(code) { where(response_code: code) }
@@ -164,7 +164,7 @@ module Spree
end
def clear_authorization_url
update_attribute(:cvv_response_message, nil)
update_attribute(:redirect_auth_url, nil)
end
private

View File

@@ -241,7 +241,8 @@ module Spree
if response.cvv_result
self.cvv_response_code = response.cvv_result['code']
self.cvv_response_message = response.cvv_result['message']
if cvv_response_message.present?
self.redirect_auth_url = response.cvv_result['redirect_auth_url']
if redirect_auth_url.present?
return require_authorization!
end
end

View File

@@ -19,6 +19,7 @@ require 'open_food_network/property_merge'
module Spree
class Product < ApplicationRecord
include LogDestroyPerformer
include ProductSortByStocks
self.belongs_to_required_by_default = false
# These columns have been moved to variant. Currently this is only for documentation purposes,
@@ -30,7 +31,7 @@ module Spree
acts_as_paranoid
searchable_attributes :meta_keywords, :sku
searchable_attributes :meta_keywords, :sku, :on_hand, :backorderable_priority
searchable_associations :properties, :variants
searchable_scopes :active, :with_properties

View File

@@ -19,4 +19,9 @@ class TagRule < ApplicationRecord
end
end
end
# The following method must be overriden in a concrete tagRule
def tags
raise NotImplementedError, 'please use concrete TagRule'
end
end

View File

@@ -14,6 +14,10 @@ class TagRule::FilterOrderCycles < TagRule
preferred_matched_order_cycles_visibility != "visible"
end
def tags
preferred_exchange_tags
end
private
def exchange_for(order_cycle)

View File

@@ -13,4 +13,8 @@ class TagRule::FilterPaymentMethods < TagRule
def reject_matched?
preferred_matched_payment_methods_visibility != "visible"
end
def tags
preferred_payment_method_tags
end
end

View File

@@ -18,5 +18,9 @@ class TagRule
def reject_matched?
preferred_matched_variants_visibility != "visible"
end
def tags
preferred_variant_tags
end
end
end

View File

@@ -13,4 +13,8 @@ class TagRule::FilterShippingMethods < TagRule
preferred_tags = preferred_shipping_method_tags.split(",")
shipping_method_tags.intersect?(preferred_tags)
end
def tags
preferred_shipping_method_tags
end
end

View File

@@ -10,8 +10,8 @@ module Api
:preferred_shopfront_taxon_order, :preferred_shopfront_producer_order,
:preferred_shopfront_order_cycle_order, :show_customer_names_to_suppliers,
:show_customer_contacts_to_suppliers,
:preferred_shopfront_product_sorting_method, :owner, :contact, :users, :tag_groups,
:default_tag_group, :require_login, :allow_guest_orders, :allow_order_changes,
:preferred_shopfront_product_sorting_method, :owner, :contact, :users,
:require_login, :allow_guest_orders, :allow_order_changes,
:logo, :promo_image, :terms_and_conditions,
:terms_and_conditions_file_name, :terms_and_conditions_updated_at,
:preferred_invoice_order_by_supplier, :preferred_product_low_stock_display,
@@ -50,41 +50,8 @@ module Api
object.terms_and_conditions_blob&.created_at&.to_s
end
def tag_groups
prioritized_tag_rules.each_with_object([]) do |tag_rule, tag_groups|
tag_group = find_match(tag_groups, tag_rule.preferred_customer_tags.
split(",").
map{ |t| { text: t } })
if tag_group[:rules].blank?
tag_groups << tag_group
tag_group[:position] = tag_groups.count
end
tag_group[:rules] << Api::Admin::TagRuleSerializer.new(tag_rule).serializable_hash
end
end
def default_tag_group
default_rules = object.tag_rules.select(&:is_default)
serialized_rules =
ActiveModel::ArraySerializer.new(default_rules,
each_serializer: Api::Admin::TagRuleSerializer)
{ tags: [], rules: serialized_rules }
end
def find_match(tag_groups, tags)
tag_groups.each do |tag_group|
return tag_group if tag_group[:tags].length == tags.length &&
(tag_group[:tags] & tags) == tag_group[:tags]
end
{ tags:, rules: [] }
end
private
def prioritized_tag_rules
object.tag_rules.prioritised.reject(&:is_default)
end
# Returns a hash of URLs for specified versions of an attachment.
#
# Example result:

View File

@@ -2,7 +2,7 @@
module Api
class PaymentSerializer < ActiveModel::Serializer
attributes :amount, :updated_at, :payment_method, :state, :cvv_response_message
attributes :amount, :updated_at, :payment_method, :state, :redirect_auth_url
def payment_method
object.payment_method.try(:name)

View File

@@ -40,7 +40,7 @@ module Checkout
# Stripe::AuthorizeResponsePatcher patches the Stripe authorization response
# so that this field stores the redirect URL. It also verifies that it is a Stripe URL.
def stripe_payment_url(payment)
payment.cvv_response_message
payment.redirect_auth_url
end
end
end

View File

@@ -5,7 +5,7 @@
# /checkout; for admin payments and subscription payemnts it's the order url.
#
# This class confirms that the payment intent matches what's in our database,
# marks the payment as complete, and removes the cvv_response_message field,
# marks the payment as complete, and removes the redirect_auth_url field,
# which we use to indicate that authorization is required. It also completes the
# Order, if appropriate.

View File

@@ -4,6 +4,13 @@
# Tag rules exists in the context of enterprise, customer, and variant_overrides,
# and are applied to variant_overrides only. Returns a Spree::Variant AR object.
# The filtering is somewhat not intuitive when they are conflicting rules in play:
# * When a variant is hidden by a default rule, the order of customer related rules doesn't matter
# ( despite the use of `TagRule::FilterProducts.prioritised` ). It will apply the "show rule"
# if any
# * When there is no default rule, the order of customer related rules doesn't matter, it will
# apply the "hide rule" if any
#
class ProductTagRulesFilterer
def initialize(distributor, customer, variants_relation)
@distributor = distributor

View File

@@ -28,7 +28,7 @@
= enterprise_form.check_box :is_primary_producer
= t('.producer')
- if spree_current_user.admin?
%td= enterprise_form.select :sells, Enterprise::SELLS, {}, class: 'select2 fullwidth'
%td= enterprise_form.select :sells, enterprise_sells_options, {}, class: 'select2 fullwidth'
%td= enterprise_form.check_box :visible, {}, 'public', 'hidden'
- if spree_current_user.admin?
%td= enterprise_form.select :owner_id, enterprise.users.map{ |e| [ e.email, e.id ] }, {}, class: "select2 fullwidth"

View File

@@ -1,3 +1,5 @@
- connected_apps_enabled.each do |type|
- connected_apps_enabled(enterprise).each do |type|
= render partial: "/admin/enterprises/form/connected_apps/#{type}",
locals: { enterprise:, connected_app: enterprise.connected_apps.public_send(type).first }
= render partial: "/admin/enterprises/form/dfc_permissions" if dfc_platforms_available?

View File

@@ -0,0 +1,30 @@
%script{type: "module", src: "https://cdn.jsdelivr.net/npm/@startinblox/core@latest/dist/index.js"}
%script{type: "module"}
:plain
window.orbit = {
client: {
name: "Orbit",
logo: "https://cdn.startinblox.com/logos/ACME.svg",
},
components: [],
getRoute: (route) => route,
getDefaultRoute: () => "",
getComponent: () => undefined,
getComponentFromRoute: () => undefined,
Swal: () => {},
defaultRoute: "",
federations: {},
componentSet: new Set(["routing", "menu", "menu-top", "autoLogin", "solid-permissioning"]),
};
:plain
<solid-permissioning
data-src="#{DfcProvider::Engine.routes.url_helpers.enterprise_platforms_url(@enterprise.id)}"
scopes-uri="https://cdn.startinblox.com/owl/dfc/taxonomies/scopes.jsonld"
noRouter
auto-lang
lang="en"
auth-token="#{form_authenticity_token}">
</solid-permissioning>
%script{type: "module", src: "https://cdn.jsdelivr.net/npm/@startinblox/solid-data-permissioning@latest/dist/index.js"}

View File

@@ -1,29 +1,25 @@
= render partial: "admin/json/injection_ams", locals: { ngModule: "admin.tagRules", name: "ruleTypes", json: @tag_rule_types.to_json }
.row{ "ng-app" => "admin.tagRules", "ng-controller": "TagRulesCtrl" }
.row
.eleven.columns.alpha.omega
%ofn-sortable{ axis: "y", handle: ".header", items: '.customer_tag', position: "tagGroup.position", "after-sort": "updateRuleCounts()" }
.no_tags{ "ng-show": "tagGroups.length == 0" }
= t('.no_tags_yet')
= render 'admin/enterprises/form/tag_rules/default_rules'
-# = render 'customer_tags'
.customer_tag{ id: "tg_{{tagGroup.position}}", "ng-repeat": "tagGroup in tagGroups" }
.header
%table
%colgroup
%col{width: '35%'}
%col{width: '65%'}
%tr
%td
%h5
= t('.for_customers_tagged')
%td
%tags-with-translation{ object: "tagGroup", max: 1, "on-tag-added": "updateTagsRulesFor(tagGroup)", "on-tag-removed": "updateTagsRulesFor(tagGroup)" }
%div{ "data-turbo": true }
- current_group_index = 0
- # We use a high enough index increment so that the default tag rule should not overlap with the tag rules
- # Rails will deal with non continous numbered tag_rules_attributes just fine, it saves us from having to manage the index state in javascript
- current_rule_index = 1000
- rules = @enterprise.tag_rules.prioritised.reject(&:is_default)
- if rules.empty?
.no_tags
= t('.no_tags_yet')
.no_rules{ "ng-show": "tagGroup.rules.length == 0" }
= t('.no_rules_yet')
.tag_rule{ "ng-repeat": "rule in tagGroup.rules" }
.add_rule.text-center
%input.button.icon-plus{ type: 'button', value: t('.add_new_rule'), "add-new-rule-to" => "addNewRuleTo", "tag-group" => "tagGroup", "new-tag-rule-dialog" => true }
.add_tag
%input.button.red.icon-plus{ type: 'button', value: t('.add_new_tag'), "ng-click": 'addNewTag()' }
= render 'admin/enterprises/form/tag_rules/default_rules', f:, current_rule_index:
#customer-tag-rule
- tag_groups(rules).each_with_index do |group, group_index|
- current_group_index = group_index + 1
= render TagRuleGroupFormComponent.new(group:, index: group_index, customer_rule_index: current_rule_index, tag_rule_types: @tag_rule_types)
- # Same as above, We use a high enough increcment so that the previous tag rule group does not overlap with the next tag rule group
- current_rule_index += 1000
.add_tag{ "data-controller": "tag-rule-group" }
= hidden_field_tag "group_index", current_group_index, { "data-tag-rule-group-target": "index" }
= hidden_field_tag "customer_rule_index", current_rule_index, { "data-tag-rule-group-target": "customerRuleIndex" }
%input.button{ type: 'button', value: t('.add_new_tag'), "data-action": "click->tag-rule-group#add" }

View File

@@ -8,12 +8,23 @@
%h5
= t('.by_default')
%i.text-big.icon-question-sign{ "data-controller": "help-modal-link", "data-action": "click->help-modal-link#open", "data-help-modal-link-target-value": "tag_rule_help_modal" }
.no_rules{ "ng-show": "defaultTagGroup.rules.length == 0" }
= t('.no_rules_yet')
.tag_rule{ "ng-repeat": "rule in defaultTagGroup.rules" }
.add_rule.text-center
%input.button.icon-plus{ type: 'button', value: t('.add_new_button'), "add-new-rule-to" => "addNewRuleTo", "tag-group" => "defaultTagGroup", "new-tag-rule-dialog" => true }
#default-tag-rule
- default_rules = @enterprise.tag_rules.select(&:is_default)
- current_rule_index = 0
- if default_rules.empty?
.no_rules
= t('.no_rules_yet')
- else
- default_rules.each_with_index do |default_rule, index|
- current_rule_index = index + 1
= render TagRuleFormComponent.new(rule: default_rule, index: index)
%hr
.add_rule.text-center
%input.button.icon-plus{ type: 'button', value: t('.add_new_button'), "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "tag_rule_add_new_default_rule" }
= render AddTagRuleModalComponent.new(id: "tag_rule_add_new_default_rule", tag_rule_types: @tag_rule_types, current_index: current_rule_index, div_id: "default-tag-rule", is_default: true)
= render HelpModalComponent.new(id: "tag_rule_help_modal") do
#tag-rule-help
.margin-bottom-30.text-center

View File

@@ -0,0 +1,4 @@
= turbo_stream.append "customer-tag-rule" do
= render TagRuleGroupFormComponent.new(group: @group, index: @index, customer_rule_index: @customer_rule_index, tag_rule_types: @tag_rule_types)
= turbo_stream.remove_all ".no_tags"

View File

@@ -7,7 +7,7 @@
%td.receival-details
= text_field_tag 'order_cycle_incoming_exchange_{{ $index }}_receival_instructions', '', 'id' => 'order_cycle_incoming_exchange_{{ $index }}_receival_instructions', 'placeholder' => t('.receival_instructions_placeholder'), 'ng-model' => 'exchange.receival_instructions'
- if type == 'distributor'
%td.tags.panel-toggle.text-center{ name: "tags", "ng-if": 'enterprises[exchange.enterprise_id].managed || order_cycle.viewing_as_coordinator' }
%td.tags.panel-toggle.text-center{ name: "tags", id: "tags", "ng-if": 'enterprises[exchange.enterprise_id].managed || order_cycle.viewing_as_coordinator' }
{{ exchange.tags.length }}
%td.collection-details
= text_field_tag 'order_cycle_outgoing_exchange_{{ $index }}_pickup_time', '', 'ng-init' => 'setPickupTimeFieldDirty($index, exchange.pickup_time)', 'id' => 'order_cycle_outgoing_exchange_{{ $index }}_pickup_time', 'required' => 'required', 'placeholder' => t('.pickup_time_placeholder'), 'ng-model' => 'exchange.pickup_time', 'ng-disabled' => '!enterprises[exchange.enterprise_id].managed && !order_cycle.viewing_as_coordinator', 'maxlength' => 35
@@ -36,5 +36,5 @@
- if type == 'distributor'
%tr.panel-row{ object: "exchange",
panels: "{products: 'exchange_products_distributed', tags: 'exchange_tags'}",
locals: "$index,exchangeTotalVariants,order_cycle,exchange,enterprises,setExchangeVariants,incomingExchangeVariantsFor,variantSuppliedToOrderCycle,initializeExchangeProductsPanel,loadMoreExchangeProducts,loadAllExchangeProducts,productsLoading",
locals: "$index,exchangeTotalVariants,order_cycle,exchange,enterprises,setExchangeVariants,incomingExchangeVariantsFor,variantSuppliedToOrderCycle,initializeExchangeProductsPanel,loadMoreExchangeProducts,loadAllExchangeProducts,productsLoading,order_cycle_form",
colspan: 5 }

View File

@@ -5,7 +5,7 @@
%h6= t('admin.product_import.index.choose_import_type')
%br
- options = { "#{t('admin.product_import.index.product_list')}" => :product_list }
- options = options.merge("#{t('admin.product_import.index.inventories')}" => :inventories) if feature?(:inventory, spree_current_user.enterprises)
- options = options.merge("#{t('admin.product_import.index.inventories')}" => :inventories) if feature?(:inventory, *spree_current_user.enterprises)
= select_tag "settings[import_into]",
options_for_select(options),
{ "data-controller": "tom-select", class: "primary inline no-search", "ng-model": "settings.import_into" }

View File

@@ -5,7 +5,7 @@
%i.icon-external-link
= t('admin.product_import.index.product_list_template')
- if feature?(:inventory, spree_current_user.enterprises)
- if feature?(:inventory, *spree_current_user.enterprises)
%a.download{href: '/inventory_template.csv'}
%i.icon-external-link
= t('admin.product_import.index.inventory_template')

View File

@@ -24,7 +24,7 @@
%td.col-inherits_properties.align-left
.content= product.inherits_properties ? 'YES' : 'NO' #TODO: consider using https://github.com/RST-J/human_attribute_values, else use I18n.t (also below)
%td.align-right
= render(VerticalEllipsisMenu::Component.new) do
= render(VerticalEllipsisMenuComponent.new) do
= link_to t('admin.products_page.actions.edit'), edit_admin_product_path(product), 'data-turbo': false
= link_to t('admin.products_page.actions.clone'), admin_clone_product_path(product), 'data-turbo-method': :post
%a{ "data-controller": "modal-link", "data-action": "click->modal-link#setModalDataSetOnConfirm click->modal-link#open",

View File

@@ -7,7 +7,7 @@
= render partial: 'product_row', locals: { f: product_form, product:, product_index: }
- product.variants.each_with_index do |variant, variant_index|
= form.fields_for("products][#{product_index}][variants_attributes][", variant, index: variant_index) do |variant_form|
= form.fields_for("products][#{product_index}][variants_attributes", variant, index: variant_index) do |variant_form|
%tr.condensed{ id: dom_id(variant), 'data-controller': "variant", 'class': "nested-form-wrapper", 'data-new-record': variant.new_record? ? "true" : false }
= render partial: 'variant_row', locals: { variant:, f: variant_form, category_options:, tax_category_options:, producer_options: }

View File

@@ -59,7 +59,8 @@
%th.align-left.col-unit_scale.with-input= t('admin.products_page.columns.unit_scale')
%th.align-left.col-unit.with-input= t('admin.products_page.columns.unit')
%th.align-left.col-price.with-input= t('admin.products_page.columns.price')
%th.align-left.col-on_hand.with-input= t('admin.products_page.columns.on_hand')
= render partial: 'spree/admin/shared/stimulus_sortable_header',
locals: { column: :on_hand, sorted: params.dig(:q, :s), default: 'name asc' }
%th.align-left.col-producer= t('admin.products_page.columns.producer')
%th.align-left.col-category= t('admin.products_page.columns.category')
%th.align-left.col-tax_category= t('admin.products_page.columns.tax_category')

View File

@@ -80,11 +80,11 @@
= error_message_on variant, :tax_category
- if feature?(:variant_tag, spree_current_user)
%td.col-tags.field.naked_inputs
= render TagListInputComponent.new(form: f, method: "tag_list", tags: variant.tag_list, placeholder: t('.add_a_tag'), aria_label: t('admin.products_page.columns.tags'))
= render TagListInputComponent.new(name: f.field_name(:tag_list), tags: variant.tag_list, placeholder: t('.add_a_tag'), aria_label: t('admin.products_page.columns.tags'))
%td.col-inherits_properties.align-left
-# empty
%td.align-right
= render(VerticalEllipsisMenu::Component.new) do
= render(VerticalEllipsisMenuComponent.new) do
- if variant.persisted?
= link_to t('admin.products_page.actions.edit'), edit_admin_product_variant_path(variant.product, variant)
- if variant.product.variants.size > 1

View File

@@ -1,19 +1,23 @@
- if @report_subtypes.present? && @report_subtypes.count > 1
%input{type: 'hidden', name: 'report_subtype', value: @report_subtype}
.row.rendering-options{ "data-controller": "csv-select" }
.row.rendering-options{ "data-controller": "csv-select metadata-toggle" }
.alpha.two.columns
= label_tag :report_format, t(".generate_report")
.omega.fourteen.columns{ style: "margin-bottom: 1.5em;" }
= select_tag :report_format, grouped_options_for_select({ |
t('.formatted_data') => { t('.on_screen') => '', "PDF" => 'pdf', t('.spreadsheet') => 'xlsx' }, |
t('.raw_data') => { "CSV" => 'csv' }, |
}), { "data-csv-select-target": "reportType", "data-action": "csv-select#handleSelectChange" }
}), { "data-csv-select-target": "reportType", "data-metadata-toggle-target": "reportType", "data-action": "csv-select#handleSelectChange metadata-toggle#handleSelectChange" }
- if @report.header_option? || @report.summary_row_option?
- if @report.header_option? || @report.summary_row_option? || @report.metadata_option?
.row
.alpha.two.columns= label_tag nil, t(".display")
.omega.fourteen.columns
- if @report.metadata_option?
%span.inline-checkbox{ style: "margin-right: 1rem;" }
= check_box_tag :display_metadata_rows, true, @rendering_options.options[:display_metadata_rows], { "disabled": "true", "data-metadata-toggle-target": "checkbox" }
= label_tag :display_metadata_rows, t(".metadata_rows"), {"class": "disabled", "data-metadata-toggle-target": "label" }
- if @report.header_option?
%span.inline-checkbox{ style: "margin-right: 1rem;" }
= check_box_tag :display_header_row, true, @rendering_options.options[:display_header_row]

View File

@@ -0,0 +1,4 @@
- unless flash[:error]
= turbo_stream.remove "tr_#{@index}"
= turbo_stream.append "flashes" do
= render(partial: 'admin/shared/flashes', locals: { flashes: flash })

View File

@@ -0,0 +1,10 @@
- if flash[:error]
= turbo_stream.append "flashes" do
= render(partial: 'admin/shared/flashes', locals: { flashes: flash })
- else
= turbo_stream.append @div_id do
= render(TagRuleFormComponent.new(rule: @default_rule,
index: @index,
customer_tags: @customer_tags,
hidden_field_customer_tag_options: { "data-tag-rule-group-form-target": "ruleCustomerTag" }))
= turbo_stream.remove_all ".no_rules"

View File

@@ -11,7 +11,7 @@
= @order.shipping_method.name
%em.fees= payment_or_shipping_price(@order.shipping_method, @order)
.two-columns
= render "delivery_details" if @order.shipping_method.delivery? || feature?(:hub_address)
= render "delivery_details" if @order.shipping_method.delivery?
- if @order.shipping_method.description.present?
%div
.summary-subtitle

View File

@@ -13,10 +13,10 @@
%form{ name: 'about', novalidate: true, "ng-controller": "RegistrationFormCtrl", "ng-submit": "selectIfValid('images', about)" }
.row
.small-12.columns
.alert-box.info{ "ofn-inline-alert": true, "ng-show": "visible" }
.alert-box.info{ "data-controller": "toggle-control", "data-toggle-control-target": "content", style: "display: block;" }
%h6{ "ng-bind" => "'registration.steps.about.success' | t:{enterprise: enterprise.name}" }
%span= t(".registration_exit_message")
%a.close{ "ng-click": "close()" } &times;
%a.close{ "data-action": "toggle-control#toggleDisplay" } &times;
.small-12.large-8.columns
.row

View File

@@ -1,4 +1,4 @@
.text-center.page-alert.fixed{ "ofn-page-alert" => true }
.text-center.page-alert.fixed{ "data-controller" => "page-alert" }
.alert-box
= render 'shared/page_alert'
%a.close{ "ng-click": "close()" } &times;
%a.close{ "data-action" => "page-alert#close" } &times;

View File

@@ -1,7 +1,7 @@
.closed-shop-header
.row
.small-12.columns
.content{ "darker-background" => true }
.content
%h4
.warning-sign
.rectangle

View File

@@ -1,4 +1,4 @@
.content{ "darker-background" => true }
.content
.row.footer-pad
.small-12.columns{ "data-controller": "login-modal" }
%strong

View File

@@ -1,4 +1,4 @@
.content.footer-pad{ "darker-background" => true, "ng-show" => "order_cycle.order_cycle_id == null" }
.content.footer-pad{ "ng-show" => "order_cycle.order_cycle_id == null" }
.row
.small-12.columns
.select-oc-message

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