Compare commits

...

178 Commits

Author SHA1 Message Date
Ahmed Ejaz
7cab04553a add test data 2025-09-18 00:51:31 +05: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
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
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
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
32c96b72ad Update all locales with the latest Transifex translations 2025-08-08 10:24:04 +10:00
Maikel
30701d61e2 Merge pull request #13232 from chitty/rails7.1
Bump Rails to 7.1
2025-08-08 10:09:58 +10:00
Carlos Chitty
45b712ddcd Set latest invoce date explicitly in Orders::GenerateInvoiceService test
Solves CI failure:
https://github.com/openfoodfoundation/openfoodnetwork/actions/runs/14760883756/job/41441014958?pr=13232
2025-08-07 17:44:52 +02:00
Carlos Chitty
3153e99497 Update OpenOrderCycleJob test "syncing remote products" to expect 58 queries instead of 59
The main point of the test is to alert us if the query count increased (https://github.com/openfoodfoundation/openfoodnetwork/pull/13232#discussion_r2199896280).
The missing query in rails 7.1:

Spree::StockItem Load  SELECT "spree_stock_items"."id", "spree_stock_items"."variant_id", "spree_stock_items"."count_on_hand", "spree_stock_items"."created_at", "spree_stock_items"."updated_at", "spree_stock_items"."backorderable", "spree_stock_items"."deleted_at", "spree_stock_items"."lock_version" FROM "spree_stock_items" WHERE "spree_stock_items"."id" = $1 LIMIT $2 FOR UPDATE
2025-08-07 17:44:52 +02:00
Carlos Chitty
a2f263e081 User Rails.env.local?
https://github.com/rails/rails/pull/46786
Solves rubocop failure in rails 7.1 bump branch https://github.com/openfoodfoundation/openfoodnetwork/actions/runs/14739687970/job/41374340281?pr=13232
2025-08-07 17:44:52 +02:00
Carlos Chitty
3cb6a2617b Do not fail tests on deprecation warnings for the next rails version (7.2) 2025-08-07 17:44:52 +02:00
Carlos Chitty
420deca437 Bump rails from 7.0.8 to 7.1.5.1 2025-08-07 17:44:52 +02:00
Filipe
76aebf8a72 Merge pull request #13436 from chahmedejaz/task/13432-decommission-old-products-screen
Decommission Old Products UI and Related Code
2025-08-07 17:39:43 +02: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
Maikel
1bfff91c72 Merge pull request #13449 from openfoodfoundation/dependabot/npm_and_yarn/tmp-0.2.4
Bump tmp from 0.2.1 to 0.2.4
2025-08-07 10:24:15 +10:00
Maikel Linke
d469552afc Fix schema version 2025-08-07 10:13:14 +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
dependabot[bot]
e6cffde8fb Bump tmp from 0.2.1 to 0.2.4
Bumps [tmp](https://github.com/raszi/node-tmp) from 0.2.1 to 0.2.4.
- [Changelog](https://github.com/raszi/node-tmp/blob/master/CHANGELOG.md)
- [Commits](https://github.com/raszi/node-tmp/compare/v0.2.1...v0.2.4)

---
updated-dependencies:
- dependency-name: tmp
  dependency-version: 0.2.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-06 18:31:11 +00: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
Gaetan Craig-Riou
3af28c4b5b Merge pull request #13441 from mkllnk/cover-more
Check more code for coverage
2025-08-04 16:49:56 +10:00
David Cook
63b864253d Merge pull request #13442 from mkllnk/puffing-billy
Add gem puffing-billy to record browser requests
2025-08-04 12:35:34 +10:00
David Cook
8efeec4301 Merge pull request #13440 from mkllnk/tidy
Remove unused test helper
2025-08-04 12:03:43 +10:00
Maikel Linke
bed33928e0 Declare simplecov as direct dependency
The undercover docs recommended to remove it from the Gemfile but that's
only valid if you use only undercover. We do rely directly on the
simplecov gem to generate reports though.
2025-08-04 11:55:26 +10:00
Maikel Linke
bb7a31b286 Update all locales with the latest Transifex translations 2025-08-01 12:37:40 +10:00
Ahmed Ejaz
75b2fe1dd4 revert API removals 2025-08-01 01:48:21 +05:00
Maikel Linke
c0924fbe5e Use new Undercover formatter for :nocov: support 2025-07-31 14:56:17 +10:00
Maikel Linke
d72bc49409 Compare coverage to upstream master when on fork 2025-07-31 14:56:17 +10:00
Maikel Linke
06867ff7ea Remove unnecessary simplecov filters
* /schemas doesn't exist.
* /lib/generators doesn't exist.
* /vendor doesn't contain rb files.
* /public doesn't contain rb files.
* /swagger doesn't contain rb files.
* /log doens't contain rb files.
2025-07-31 14:56:17 +10:00
Maikel Linke
76a1fe7767 Ignore inaccurate coverage of rake tasks
I tried several ways to get code coverage for rake tasks but I haven't
succeeded yet. Somehow rake is confusing simplecov.
2025-07-31 14:56:11 +10:00
Maikel Linke
3363c523ea Check more code for coverage
* ApplicationJob should be covered by tests.
* Spec should all be executed, except `xit` which should be avoided and
  can be flagged.
2025-07-31 14:53:51 +10:00
Maikel
91628f8daa Merge pull request #13443 from openfoodfoundation/dependabot/npm_and_yarn/floating-ui/dom-1.7.3
Bump @floating-ui/dom from 1.7.2 to 1.7.3
2025-07-31 11:52:14 +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
dependabot[bot]
f3dfbab109 Bump @floating-ui/dom from 1.7.2 to 1.7.3
Bumps [@floating-ui/dom](https://github.com/floating-ui/floating-ui/tree/HEAD/packages/dom) from 1.7.2 to 1.7.3.
- [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.3/packages/dom)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-30 10:00:39 +00:00
Maikel Linke
d01474ebcd Ignore Chrome's automatic requests to Google services 2025-07-30 12:25:34 +10:00
Maikel Linke
a062a7b697 Add Billy proxy to Chrome in system specs
And demonstrate the use of puffing-billy browser proxy.

Billy can cache and record responses to browser requests. For that to
work we need to allow network connections and disable VCR. But instead I
found that the Billy proxy is just like any other Ruby backend code and
its connections can be recorded with VCR instead.

And instead of stubbing requests via Billy.proxy, we can use standard
Webmock `stub_request`. Now we use puffing-billy just to relay browser
requests via our Ruby app.
2025-07-29 14:37:27 +10:00
Maikel Linke
fe8b805e1f Add gem puffing-billy 2025-07-29 14:37:27 +10:00
Maikel Linke
f3f43225cb Remove unused test helper 2025-07-29 13:42:51 +10:00
Maikel
65604f5b04 Merge pull request #13437 from dacook/remove-unused-method
Remove unused method
2025-07-28 16:29:15 +10:00
David Cook
661bb29029 Remove unused method
The name doesn't appear in the codebase so I guess it's unused.
2025-07-28 13:19:16 +10:00
Ahmed Ejaz
df4cf4b768 Fix specs 2025-07-27 07:58:04 +05:00
Ahmed Ejaz
3f39d94bd3 Remove conditional rendering for previous page icon in pagination 2025-07-27 07:21:10 +05:00
Ahmed Ejaz
acfe3f6589 Remove admin_style_v3 feature toggle and related conditional logic 2025-07-27 07:20:16 +05:00
Ahmed Ejaz
1717c5376b Remove deprecated migrations for admin style v3 activation 2025-07-27 07:11:07 +05:00
Ahmed Ejaz
1426b6eeb7 Remove legacy admin styles in favor of v3 styling
Completes migration to the new admin v3 styling system by:
- Removing conditional stylesheet inclusion in admin head
- Deleting all legacy admin style files and components
- Making admin-style-v3 the default and only stylesheet

This change reduces maintenance overhead and simplifies the admin styling codebase by removing the old styling system that was being conditionally loaded based on feature flags.
2025-07-27 07:02:53 +05:00
Ahmed Ejaz
188b2eb754 Simplify pagination next button by removing conditional icon rendering 2025-07-27 06:44:02 +05:00
Ahmed Ejaz
6e055ddbdf Remove icon parameters from admin navigation tabs for simplification 2025-07-27 06:32:44 +05:00
Ahmed Ejaz
025fc784a8 Refactor products_return_to_url method to remove url_filters parameter and simplify usage in views 2025-07-27 06:26:12 +05:00
Ahmed Ejaz
fefd0239e6 Remove unused product image controller and directive; delete product image update route 2025-07-27 06:15:14 +05:00
Ahmed Ejaz
0fa67c69fd Remove bulk product update functionality
Removes the bulk product update feature and its associated components:
- Removes Angular-based bulk product editing controller and views
- Deletes bulk product API endpoints and related controller actions
- Removes product cloning and variant deletion functionality
- Removes associated JavaScript tests and specs

This appears to be part of a larger effort to modernize/simplify the product management interface, removing legacy Angular-based bulk editing in favor of a different approach.
2025-07-27 06:03:14 +05:00
Ahmed Ejaz
44cbe55c96 Update product routes and views for consistency and clarity 2025-07-27 05:25:50 +05:00
Ahmed Ejaz
6da1200b64 Refactor product routes to remove feature toggle constraints and simplify access 2025-07-24 02:30:37 +05:00
175 changed files with 58157 additions and 4762 deletions

13
.github/pull_request.json vendored Normal file
View File

@@ -0,0 +1,13 @@
{
"pull_request": {
"number": 13490,
"title": "Bump rails from 7.0.4 to 7.0.8",
"id": 99999999,
"user": { "login": "dependabot[bot]" }
},
"repository": {
"owner": { "login": "openfoodnetwork" },
"name": "openfoodnetwork"
},
"sender": { "login": "dependabot[bot]" }
}

View File

@@ -410,6 +410,6 @@ jobs:
include-hidden-files: true
- name: Compare SimpleCov results with Undercover
run: |
git fetch --no-tags origin master:master
git fetch --no-tags origin ${{ github.event.pull_request.base.ref }}:master
bundle exec undercover
if: ${{ github.ref != 'refs/heads/master' }} # Does not run on master, as we can't fetch master in the master branch

View File

@@ -0,0 +1,139 @@
name: Auto-move Dependabot PRs to Code Review
on:
pull_request:
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: Move PR to Code Review in Project v2
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const projectNumber = 8; // for "OFN Delivery board"
const org = context.repo.owner;
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}'`);

View File

@@ -16,6 +16,7 @@ AllCops:
- node_modules/**/*
# Excluding: inadequate Naming/FileName rule rejects GemFile name with camelcase
- engines/web/Gemfile
- .undercover
Bundler/DuplicatedGem:
Enabled: false

View File

@@ -2,19 +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 '/jobs/application_job.rb'
add_filter '/schemas/'
add_filter '/lib/generators'
add_filter '/spec/'
add_filter '/vendor/'
add_filter '/public'
add_filter '/swagger'
add_filter '/config/' # to include engine config
add_filter '/script'
add_filter '/log'
add_filter '/db'
add_filter '/lib/tasks/sample_data/'
formatter SimpleCov::Formatter::SimpleFormatter
end

View File

@@ -1,5 +1,9 @@
#!/bin/env ruby
# frozen_string_literal: true
-l coverage/lcov/openfoodnetwork.lcov
-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

@@ -152,6 +152,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,14 +167,13 @@ 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
gem 'pdf-reader'
gem 'puffing-billy'
gem 'rails-controller-testing'
gem 'simplecov', require: false
gem 'simplecov-lcov', require: false
gem 'undercover', require: false
gem 'vcr', require: false
gem 'webmock', require: false

View File

@@ -48,54 +48,58 @@ PATH
GEM
remote: https://rubygems.org/
specs:
Ascii85 (1.1.0)
actioncable (7.0.8)
actionpack (= 7.0.8)
activesupport (= 7.0.8)
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)
actionmailbox (7.0.8)
actionpack (= 7.0.8)
activejob (= 7.0.8)
activerecord (= 7.0.8)
activestorage (= 7.0.8)
activesupport (= 7.0.8)
zeitwerk (~> 2.6)
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.0.8)
actionpack (= 7.0.8)
actionview (= 7.0.8)
activejob (= 7.0.8)
activesupport (= 7.0.8)
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.0)
actionpack (7.0.8)
actionview (= 7.0.8)
activesupport (= 7.0.8)
rack (~> 2.0, >= 2.2.4)
rails-dom-testing (~> 2.2)
actionpack (7.1.5.2)
actionview (= 7.1.5.2)
activesupport (= 7.1.5.2)
nokogiri (>= 1.8.5)
racc
rack (>= 2.2.4)
rack-session (>= 1.0.1)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
actionpack-action_caching (1.2.2)
actionpack (>= 4.0.0)
actiontext (7.0.8)
actionpack (= 7.0.8)
activerecord (= 7.0.8)
activestorage (= 7.0.8)
activesupport (= 7.0.8)
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.0.8)
activesupport (= 7.0.8)
actionview (7.1.5.2)
activesupport (= 7.1.5.2)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
active_model_serializers (0.8.4)
activemodel (>= 3.0)
active_storage_validations (1.1.4)
@@ -103,8 +107,8 @@ GEM
activemodel (>= 5.2.0)
activestorage (>= 5.2.0)
activesupport (>= 5.2.0)
activejob (7.0.8)
activesupport (= 7.0.8)
activejob (7.1.5.2)
activesupport (= 7.1.5.2)
globalid (>= 0.3.6)
activemerchant (1.133.0)
activesupport (>= 4.2)
@@ -112,11 +116,12 @@ GEM
i18n (>= 0.6.9)
nokogiri (~> 1.4)
rexml (~> 3.2.5)
activemodel (7.0.8)
activesupport (= 7.0.8)
activerecord (7.0.8)
activemodel (= 7.0.8)
activesupport (= 7.0.8)
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)
activerecord-postgresql-adapter (0.0.1)
@@ -128,17 +133,24 @@ GEM
multi_json (~> 1.11, >= 1.11.2)
rack (>= 2.0.8, < 4)
railties (>= 6.1)
activestorage (7.0.8)
actionpack (= 7.0.8)
activejob (= 7.0.8)
activerecord (= 7.0.8)
activesupport (= 7.0.8)
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)
mini_mime (>= 1.1.0)
activesupport (7.0.8)
activesupport (7.1.5.2)
base64
benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1)
mutex_m
securerandom (>= 0.3)
tzinfo (~> 2.0)
acts-as-taggable-on (10.0.0)
activerecord (>= 6.1, < 7.2)
@@ -177,9 +189,10 @@ 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)
bigdecimal (3.2.2)
bindata (2.5.0)
bindex (0.8.1)
@@ -188,7 +201,7 @@ GEM
bugsnag (6.26.4)
concurrent-ruby (~> 1.0)
builder (3.2.4)
bullet (7.1.6)
bullet (8.0.8)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11)
cable_ready (5.0.6)
@@ -208,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.3.7)
childprocess (5.0.0)
choice (0.2.0)
chronic (0.10.2)
@@ -228,8 +243,9 @@ 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.3)
cookiejar (0.3.4)
crack (1.0.0)
bigdecimal
rexml
@@ -248,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)
@@ -269,11 +285,25 @@ GEM
digest (3.1.1)
docile (1.4.0)
dotenv (3.1.2)
drb (2.2.3)
em-http-request (1.1.7)
addressable (>= 2.3.4)
cookiejar (!= 0.3.1)
em-socksify (>= 0.3)
eventmachine (>= 1.0.3)
http_parser.rb (>= 0.6.0)
em-socksify (0.3.3)
base64
eventmachine (>= 1.0.0.beta.4)
em-synchrony (1.0.6)
eventmachine (>= 1.0.0.beta.1)
email_validator (2.2.4)
activemodel
erubi (1.12.0)
et-orbi (1.2.7)
et-orbi (1.3.0)
tzinfo
eventmachine (1.2.7)
eventmachine_httpserver (0.2.1)
excon (0.81.0)
execjs (2.7.0)
factory_bot (6.2.0)
@@ -323,8 +353,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)
@@ -347,6 +377,7 @@ GEM
hashie (5.0.0)
highline (2.0.3)
htmlentities (4.3.4)
http_parser.rb (0.8.0)
i18n (1.14.5)
concurrent-ruby (~> 1.0)
i18n-js (3.9.2)
@@ -420,7 +451,8 @@ GEM
listen (3.9.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
loofah (2.22.0)
logger (1.7.0)
loofah (2.24.1)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.8.1)
@@ -440,7 +472,7 @@ GEM
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)
@@ -448,9 +480,10 @@ GEM
msgpack (1.7.2)
multi_json (1.15.0)
multi_xml (0.6.0)
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)
@@ -461,7 +494,7 @@ GEM
net-protocol
newrelic_rpm (9.9.0)
nio4r (2.7.1)
nokogiri (1.16.5)
nokogiri (1.18.9)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
nokogiri-html5-inference (0.3.0)
@@ -513,9 +546,9 @@ 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
@@ -527,6 +560,14 @@ GEM
psych (5.1.2)
stringio
public_suffix (5.0.5)
puffing-billy (4.0.2)
addressable (~> 2.5)
em-http-request (~> 1.1, >= 1.1.0)
em-synchrony
eventmachine (~> 1.2)
eventmachine_httpserver
http_parser.rb (~> 0.8.0)
multi_json
puma (6.5.0)
nio4r (~> 2.0)
query_count (1.1.1)
@@ -534,7 +575,7 @@ GEM
railties (>= 4.2)
raabro (1.4.0)
racc (1.8.1)
rack (2.2.11)
rack (2.2.14)
rack-mini-profiler (2.3.4)
rack (>= 1.2.0)
rack-oauth2 (2.2.1)
@@ -555,20 +596,23 @@ GEM
rack-test (2.1.0)
rack (>= 1.3)
rack-timeout (0.7.0)
rails (7.0.8)
actioncable (= 7.0.8)
actionmailbox (= 7.0.8)
actionmailer (= 7.0.8)
actionpack (= 7.0.8)
actiontext (= 7.0.8)
actionview (= 7.0.8)
activejob (= 7.0.8)
activemodel (= 7.0.8)
activerecord (= 7.0.8)
activestorage (= 7.0.8)
activesupport (= 7.0.8)
rackup (1.0.1)
rack (< 3)
webrick
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.0.8)
railties (= 7.1.5.2)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1)
@@ -582,20 +626,21 @@ GEM
activesupport (>= 4.2)
choice (~> 0.2.0)
ruby-graphviz (~> 1.2)
rails-html-sanitizer (1.6.0)
rails-html-sanitizer (1.6.1)
loofah (~> 2.21)
nokogiri (~> 1.14)
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.9)
i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 8)
rails_safe_tasks (1.0.0)
railties (7.0.8)
actionpack (= 7.0.8)
activesupport (= 7.0.8)
method_source
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)
zeitwerk (~> 2.5)
thor (~> 1.0, >= 1.2.2)
zeitwerk (~> 2.6)
rainbow (3.1.1)
rake (13.2.1)
ransack (4.1.1)
@@ -729,6 +774,7 @@ GEM
sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3)
sd_notify (0.1.1)
securerandom (0.4.1)
semantic_range (3.0.0)
shoulda-matchers (6.2.0)
activesupport (>= 5.2.0)
@@ -746,7 +792,6 @@ GEM
simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1)
simplecov-html (0.12.3)
simplecov-lcov (0.8.0)
simplecov_json_formatter (0.1.4)
spreadsheet_architect (5.0.0)
caxlsx (>= 3.3.0, < 4)
@@ -794,12 +839,12 @@ 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)
ttfunk (1.8.0)
bigdecimal (~> 3.1)
turbo-rails (2.0.5)
actionpack (>= 6.0.0)
activejob (>= 6.0.0)
@@ -817,8 +862,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)
@@ -858,7 +903,7 @@ GEM
rack-proxy (>= 0.6.1)
railties (>= 5.2)
semantic_range (>= 2.3.0)
webrick (1.8.1)
webrick (1.8.2)
websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
@@ -866,7 +911,7 @@ 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)
@@ -898,6 +943,7 @@ DEPENDENCIES
cable_ready
cancancan (~> 1.15.0)
capybara
capybara-shadowdom
catalog!
coffee-rails (~> 5.0.0)
combine_pdf
@@ -961,6 +1007,7 @@ DEPENDENCIES
pg (~> 1.2.3)
private_address_check
pry (~> 0.13.0)
puffing-billy
puma
query_count
rack-mini-profiler (< 3.0.0)
@@ -992,7 +1039,6 @@ DEPENDENCIES
sidekiq
sidekiq-scheduler
simplecov
simplecov-lcov
spreadsheet_architect
spring
spring-commands-rspec
@@ -1002,7 +1048,6 @@ DEPENDENCIES
stimulus_reflex_testing!
stringex (~> 2.8.5)
stripe
timecop
turbo-rails
turbo_power
undercover

View File

@@ -1,390 +0,0 @@
angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout, $filter, $http, $window, $location, BulkProducts, DisplayProperties, DirtyProducts, VariantUnitManager, StatusMessage, producers, Taxons, Columns, tax_categories, RequestMonitor, SortOptions, ErrorsParser, ProductFiltersUrl) ->
$scope.StatusMessage = StatusMessage
$scope.columns = Columns.columns
$scope.variant_unit_options = VariantUnitManager.variantUnitOptions()
$scope.RequestMonitor = RequestMonitor
$scope.pagination = BulkProducts.pagination
$scope.per_page_options = [
{id: 15, name: t('js.admin.orders.index.per_page', results: 15)},
{id: 50, name: t('js.admin.orders.index.per_page', results: 50)},
{id: 100, name: t('js.admin.orders.index.per_page', results: 100)}
]
$scope.q = {
producerFilter: ""
categoryFilter: ""
importDateFilter: ""
query: ""
sorting: ""
}
$scope.sorting = "name asc"
$scope.producers = producers
$scope.taxons = Taxons.all
$scope.tax_categories = tax_categories
$scope.page = 1
$scope.per_page = 15
$scope.products = BulkProducts.products
$scope.DisplayProperties = DisplayProperties
$scope.sortOptions = SortOptions
$scope.initialise = ->
$scope.q = ProductFiltersUrl.loadFromUrl($location.search())
$scope.fetchProducts()
$scope.$watchCollection '[q.query, q.producerFilter, q.categoryFilter, q.importDateFilter, per_page]', ->
$scope.page = 1 # Reset page when changing filters for new search
$scope.changePage = (newPage) ->
$scope.page = newPage
$scope.fetchProducts()
$scope.fetchProducts = ->
removeClearedValues()
params = {
'q[name_cont]': $scope.q.query,
'q[variants_supplier_id_eq]': $scope.q.producerFilter,
'q[variants_primary_taxon_id_eq]': $scope.q.categoryFilter,
'q[s]': $scope.sorting,
import_date: $scope.q.importDateFilter,
page: $scope.page,
per_page: $scope.per_page
}
RequestMonitor.load(BulkProducts.fetch(params).$promise).then ->
# update url with the filters used
$location.search(ProductFiltersUrl.generate($scope.q))
$scope.resetProducts()
removeClearedValues = ->
delete $scope.q.producerFilter if $scope.q.producerFilter == "0"
delete $scope.q.categoryFilter if $scope.q.categoryFilter == "0"
delete $scope.q.importDateFilter if $scope.q.importDateFilter == "0"
$timeout ->
if $scope.showLatestImport
$scope.q.importDateFilter = $scope.importDates[1].id
$scope.resetProducts = ->
DirtyProducts.clear()
StatusMessage.clear()
$scope.updateOnHand = (product) ->
on_demand_variants = []
if product.variants
on_demand_variants = (variant for id, variant of product.variants when variant.on_demand)
unless product.on_demand || on_demand_variants.length > 0
product.on_hand = $scope.onHand(product)
$scope.onHand = (product) ->
onHand = 0
if product.hasOwnProperty("variants") and product.variants instanceof Object
for id, variant of product.variants
onHand = onHand + parseInt(if variant.on_hand > 0 then variant.on_hand else 0)
else
onHand = "error"
onHand
$scope.shiftTab = (tab) ->
$scope.visibleTab.visible = false unless $scope.visibleTab == tab || $scope.visibleTab == undefined
tab.visible = !tab.visible
$scope.visibleTab = tab
$scope.resetSelectFilters = ->
$scope.q.query = ""
$scope.q.producerFilter = "0"
$scope.q.categoryFilter = "0"
$scope.q.importDateFilter = "0"
$scope.fetchProducts()
$scope.$watch 'sortOptions', (sort) ->
return unless sort && sort.predicate != ""
$scope.sorting = sort.getSortingExpr(defaultDirection: "asc")
$scope.fetchProducts()
, true
confirm_unsaved_changes = () ->
(DirtyProducts.count() > 0 and confirm(t("unsaved_changes_confirmation"))) or (DirtyProducts.count() == 0)
editProductUrl = (product, variant) ->
"/admin/products/" + product.id + ((if variant then "/variants/" + variant.id else "")) + "/edit"
$scope.editWarn = (product, variant) ->
if confirm_unsaved_changes()
$window.location.href = ProductFiltersUrl.buildUrl(editProductUrl(product, variant), $scope.q)
$scope.toggleShowAllVariants = ->
showVariants = !DisplayProperties.showVariants 0
$scope.products.forEach (product) ->
DisplayProperties.setShowVariants product.id, showVariants
DisplayProperties.setShowVariants 0, showVariants
$scope.addVariant = (product) ->
# Set new variant category to same as last product variant category to keep compactibility with deleted variant callback to set new variant category
newVariantId = $scope.nextVariantId();
newVariantCategoryId = product.variants[product.variants.length - 1]?.category_id
product.variants.push
id: newVariantId
unit_value: null
unit_description: null
on_demand: false
display_as: null
display_name: null
on_hand: null
price: null
tax_category_id: null
category_id: newVariantCategoryId
DisplayProperties.setShowVariants product.id, true
DirtyProducts.addVariantProperty(product.id, newVariantId, 'category_id', newVariantCategoryId)
$scope.nextVariantId = ->
$scope.variantIdCounter = 0 unless $scope.variantIdCounter?
$scope.variantIdCounter -= 1
$scope.variantIdCounter
$scope.deleteProduct = (product) ->
if confirm(t('are_you_sure'))
$http(
method: "DELETE"
url: "/api/v0/products/" + product.id
).then (response) ->
$scope.products.splice $scope.products.indexOf(product), 1
DirtyProducts.deleteProduct product.id
$scope.displayDirtyProducts()
$scope.deleteVariant = (product, variant) ->
if product.variants.length > 1
if !$scope.variantSaved(variant)
$scope.removeVariant(product, variant)
else
if confirm(t("are_you_sure"))
$http(
method: "DELETE"
url: "/api/v0/products/" + product.id + "/variants/" + variant.id
).then (response) ->
$scope.removeVariant(product, variant)
else
alert(t("delete_product_variant"))
$scope.removeVariant = (product, variant) ->
product.variants.splice product.variants.indexOf(variant), 1
DirtyProducts.deleteVariant product.id, variant.id
$scope.displayDirtyProducts()
$scope.cloneProduct = (product) ->
BulkProducts.cloneProduct product
$scope.hasVariants = (product) ->
product.variants.length > 0
$scope.hasUnit = (variant) ->
variant.variant_unit_with_scale?
$scope.variantSaved = (variant) ->
variant.hasOwnProperty('id') && variant.id > 0
$scope.hasOnDemandVariants = (product) ->
(variant for id, variant of product.variants when variant.on_demand).length > 0
$scope.submitProducts = ->
# Pack pack $scope.products, so they will match the list returned from the server,
# then pack $scope.dirtyProducts, ensuring that the correct product info is sent to the server.
$scope.packProduct product for id, product of $scope.products
$scope.packProduct product for id, product of DirtyProducts.all()
productsToSubmit = filterSubmitProducts(DirtyProducts.all())
if productsToSubmit.length > 0
$scope.updateProducts productsToSubmit # Don't submit an empty list
else
StatusMessage.display 'alert', t("products_change")
$scope.updateProducts = (productsToSubmit) ->
$scope.displayUpdating()
$http(
method: "POST"
url: "/admin/products/bulk_update"
data:
products: productsToSubmit
filters:
'q[name_cont]': $scope.q.query
'q[variants_supplier_id_eq]': $scope.q.producerFilter
'q[variants_primary_taxon_id_eq]': $scope.q.categoryFilter
'q[s]': $scope.sorting
import_date: $scope.q.importDateFilter
page: $scope.page
per_page: $scope.per_page
).then((response) ->
DirtyProducts.clear()
BulkProducts.updateVariantLists(response.data.products || [])
$timeout -> $scope.displaySuccess()
).catch (response) ->
if response.status == 400 && response.data.errors?
errorsString = ErrorsParser.toString(response.data.errors, response.status)
$scope.displayFailure t("products_update_error") + "\n" + errorsString
else
$scope.displayFailure t("products_update_error_data") + response.status
$scope.cancel = (destination) ->
$window.location = destination
$scope.packProduct = (product) ->
if product.variants
for id, variant of product.variants
$scope.packVariant variant
$scope.packVariant = (variant) ->
if variant.variant_unit_with_scale
match = variant.variant_unit_with_scale.match(/^([^_]+)_([\d\.]+)$/)
if match
variant.variant_unit = match[1]
variant.variant_unit_scale = parseFloat(match[2])
else
variant.variant_unit = variant.variant_unit_with_scale
variant.variant_unit_scale = null
if variant.hasOwnProperty("unit_value_with_description")
match = variant.unit_value_with_description.match(/^([\d\.\,]+(?= |$)|)( |)(.*)$/)
if match
variant.unit_value = parseFloat(match[1].replace(",", "."))
variant.unit_value = null if isNaN(variant.unit_value)
if variant.unit_value && variant.variant_unit_scale
variant.unit_value = parseFloat(window.bigDecimal.multiply(variant.unit_value, variant.variant_unit_scale, 2))
variant.unit_description = match[3]
$scope.incrementLimit = ->
if $scope.limit < $scope.products.length
$scope.limit = $scope.limit + 5
$scope.displayUpdating = ->
StatusMessage.display 'progress', t("saving")
$scope.displaySuccess = ->
StatusMessage.display 'success',t("products_changes_saved")
$scope.bulk_product_form.$setPristine()
$scope.displayFailure = (failMessage) ->
StatusMessage.display 'failure', t("products_update_error_msg") + " #{failMessage}"
$scope.displayDirtyProducts = ->
count = DirtyProducts.count()
switch count
when 0 then StatusMessage.clear()
when 1 then StatusMessage.display 'notice', t("one_product_unsaved")
else StatusMessage.display 'notice', t("products_unsaved", n: count)
filterSubmitProducts = (productsToFilter) ->
filteredProducts = []
if productsToFilter instanceof Object
angular.forEach productsToFilter, (product) ->
if product.hasOwnProperty("id")
filteredProduct = {id: product.id}
filteredVariants = []
hasUpdatableProperty = false
if product.hasOwnProperty("variants")
angular.forEach product.variants, (variant) ->
result = filterSubmitVariant variant
filteredVariant = result.filteredVariant
variantHasUpdatableProperty = result.hasUpdatableProperty
filteredVariants.push filteredVariant if variantHasUpdatableProperty
if product.hasOwnProperty("name")
filteredProduct.name = product.name
hasUpdatableProperty = true
if product.hasOwnProperty("price")
filteredProduct.price = product.price
hasUpdatableProperty = true
if product.hasOwnProperty("on_hand") and filteredVariants.length == 0 #only update if no variants present
filteredProduct.on_hand = product.on_hand
hasUpdatableProperty = true
if product.hasOwnProperty("on_demand") and filteredVariants.length == 0 #only update if no variants present
filteredProduct.on_demand = product.on_demand
hasUpdatableProperty = true
if product.hasOwnProperty("inherits_properties")
filteredProduct.inherits_properties = product.inherits_properties
hasUpdatableProperty = true
if filteredVariants.length > 0 # Note that the name of the property changes to enable mass assignment of variants attributes with rails
filteredProduct.variants_attributes = filteredVariants
hasUpdatableProperty = true
filteredProducts.push filteredProduct if hasUpdatableProperty
filteredProducts
filterSubmitVariant = (variant) ->
hasUpdatableProperty = false
filteredVariant = {}
if not variant.deleted_at? and variant.hasOwnProperty("id")
filteredVariant.id = variant.id unless variant.id <= 0
if variant.hasOwnProperty("sku")
filteredVariant.sku = variant.sku
hasUpdatableProperty = true
if variant.hasOwnProperty("on_hand")
filteredVariant.on_hand = variant.on_hand
hasUpdatableProperty = true
if variant.hasOwnProperty("on_demand")
filteredVariant.on_demand = variant.on_demand
hasUpdatableProperty = true
if variant.hasOwnProperty("price")
filteredVariant.price = variant.price
hasUpdatableProperty = true
if variant.hasOwnProperty("unit_value")
filteredVariant.unit_value = variant.unit_value
hasUpdatableProperty = true
if variant.hasOwnProperty("unit_description")
filteredVariant.unit_description = variant.unit_description
hasUpdatableProperty = true
if variant.hasOwnProperty("display_name")
filteredVariant.display_name = variant.display_name
hasUpdatableProperty = true
if variant.hasOwnProperty("tax_category_id")
filteredVariant.tax_category_id = variant.tax_category_id
hasUpdatableProperty = true
if variant.hasOwnProperty("category_id")
filteredVariant.primary_taxon_id = variant.category_id
hasUpdatableProperty = true
if variant.hasOwnProperty("display_as")
filteredVariant.display_as = variant.display_as
hasUpdatableProperty = true
if variant.hasOwnProperty("producer_id")
filteredVariant.supplier_id = variant.producer_id
hasUpdatableProperty = true
if variant.hasOwnProperty("variant_unit_with_scale")
filteredVariant.variant_unit = variant.variant_unit
filteredVariant.variant_unit_scale = variant.variant_unit_scale
hasUpdatableProperty = true
if variant.hasOwnProperty("variant_unit_name")
filteredVariant.variant_unit_name = variant.variant_unit_name
hasUpdatableProperty = true
{filteredVariant: filteredVariant, hasUpdatableProperty: hasUpdatableProperty}
toObjectWithIDKeys = (array) ->
object = {}
for i of array
if array[i] instanceof Object and array[i].hasOwnProperty("id")
object[array[i].id] = angular.copy(array[i])
object[array[i].id].variants = toObjectWithIDKeys(array[i].variants) if array[i].hasOwnProperty("variants") and array[i].variants instanceof Array
object

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,8 +0,0 @@
angular.module("ofn.admin").controller "ProductImageCtrl", ($scope, ProductImageService) ->
$scope.imageUploader = ProductImageService.imageUploader
$scope.imagePreview = ProductImageService.imagePreview
$scope.$watch 'product.image_url', (newValue, oldValue) ->
if newValue != oldValue
$scope.imagePreview = newValue
$scope.uploadModal.close()

View File

@@ -1,6 +0,0 @@
angular.module("ofn.admin").directive "imageModal", ($modal, ProductImageService) ->
restrict: 'C'
link: (scope, elem, attrs, ctrl) ->
elem.on "click", (ev) =>
scope.uploadModal = $modal.open(templateUrl: 'admin/modals/image_upload.html', controller: ctrl, scope: scope, windowClass: 'simple-modal')
ProductImageService.configure(scope.product)

View File

@@ -1,6 +0,0 @@
angular.module("admin.resources").factory 'ProductResource', ($resource) ->
$resource('/admin/product/:id/:action.json', {}, {
'index':
url: '/api/v0/products/bulk_products.json'
method: 'GET'
})

View File

@@ -1,76 +0,0 @@
angular.module("ofn.admin").factory "BulkProducts", (ProductResource, dataFetcher, $http) ->
new class BulkProducts
products: []
pagination: {}
fetch: (params) ->
ProductResource.index params, (data) =>
@products.length = 0
@addProducts data.products
angular.extend(@pagination, data.pagination)
cloneProduct: (product) ->
$http.post("/api/v0/products/" + product.id + "/clone").then (response) =>
dataFetcher("/api/v0/products/" + response.data.id + "?template=bulk_show").then (newProduct) =>
@unpackProduct newProduct
@insertProductAfter(product, newProduct)
updateVariantLists: (serverProducts) ->
for server_product in serverProducts
product = @findProductInList(server_product.id, @products)
product.variants = server_product.variants
@loadVariantUnitValues product.variants
find: (id) ->
@findProductInList id, @products
findProductInList: (id, product_list) ->
products = (product for product in product_list when product.id == id)
if products.length == 0 then null else products[0]
addProducts: (products) ->
for product in products
@unpackProduct product
@products.push product
insertProductAfter: (product, newProduct) ->
index = @products.indexOf(product)
@products.splice(index + 1, 0, newProduct)
unpackProduct: (product) ->
@loadVariantUnit product
loadVariantUnit: (product) ->
@loadVariantUnitValues product.variants if product.variants
loadVariantUnitValues: (variants) ->
for variant in variants
@loadVariantUnitValue variant
loadVariantUnitValue: (variant) ->
variant.variant_unit_with_scale =
if variant.variant_unit && variant.variant_unit_scale && variant.variant_unit != 'items'
"#{variant.variant_unit}_#{variant.variant_unit_scale}"
else if variant.variant_unit
variant.variant_unit
else
null
unit_value = @variantUnitValue variant
unit_value = if unit_value? then unit_value else ''
variant.unit_value_with_description = "#{unit_value} #{variant.unit_description || ''}".trim()
variantUnitValue: (variant) ->
if variant.unit_value?
if variant.variant_unit_scale
variant_unit_value = @divideAsInteger variant.unit_value, variant.variant_unit_scale
parseFloat(window.bigDecimal.round(variant_unit_value, 2))
else
variant.unit_value
else
null
# forces integer division to avoid javascript floating point imprecision
# using one billion as the multiplier so that it works for numbers with up to 9 decimal places
divideAsInteger: (a, b) ->
(a * 1000000000) / (b * 1000000000)

View File

@@ -54,7 +54,7 @@ module Api
def error_during_processing(exception)
Alert.raise(exception)
if Rails.env.development? || Rails.env.test?
if Rails.env.local?
render status: :unprocessable_entity,
json: json_api_error(exception.message, meta: exception.backtrace)
else

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

@@ -19,11 +19,6 @@ module Spree
before_action :load_spree_api_key, only: [:index, :variant_overrides]
before_action :strip_new_properties, only: [:create, :update]
def index
@current_user = spree_current_user
@show_latest_import = params[:latest_import] || false
end
def show
session[:return_to] ||= request.referer
redirect_to( action: :edit )
@@ -65,28 +60,6 @@ module Spree
end
end
def bulk_update
product_set = product_set_from_params
product_set.collection.each { |p| authorize! :update, p }
if product_set.save
redirect_to main_app.bulk_products_api_v0_products_path(bulk_index_query)
elsif product_set.errors.present?
render json: { errors: product_set.errors }, status: :bad_request
else
render body: nil, status: :internal_server_error
end
end
def clone
@new = @product.duplicate
raise "Clone failed" unless @new.save
flash[:success] = t('.success')
redirect_to spree.admin_products_url
end
def group_buy_options
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
end

View File

@@ -26,8 +26,8 @@ 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?
(connected_apps_enabled(enterprise).present? ||
dfc_platforms_available?)
show_inventory_settings = feature?(:inventory, spree_current_user.enterprises) && is_shop
show_options = {
@@ -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?
DfcProvider::PlatformsController::PLATFORM_IDS.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,6 +71,11 @@ 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
private
def build_enterprise_side_menu_items(is_shop:, show_options: ) # rubocop:disable Metrics/MethodLength

View File

@@ -32,12 +32,8 @@ module Admin
[precised_unit_value, variant.unit_description].compact_blank.join(" ")
end
def products_return_to_url(url_filters)
if feature?(:admin_style_v3, spree_current_user)
return session[:products_return_to_url] || admin_products_url
end
"#{admin_products_path}#{url_filters.empty? ? '' : "#?#{url_filters.to_query}"}"
def products_return_to_url
session[:products_return_to_url] || admin_products_url
end
# if user hasn't saved any preferences on products page and there's only one producer;

View File

@@ -5,10 +5,6 @@ module CheckoutHelper
order.ship_address == order.bill_address
end
def guest_checkout_allowed?
current_order.distributor.allow_guest_orders?
end
def checkout_adjustments_for(order, opts = {})
exclude = opts[:exclude] || {}
reject_zero_amount = opts.fetch(:reject_zero_amount, true)

View File

@@ -29,13 +29,7 @@ module Spree
scope: [:admin, :tab]).capitalize
css_classes = []
if options[:icon] && !feature?(:admin_style_v3, spree_current_user)
link = link_to_with_icon(options[:icon], titleized_label, destination_url)
css_classes << 'tab-with-icon'
else
link = link_to(titleized_label, destination_url)
end
link = link_to(titleized_label, destination_url)
selected = if options[:match_path]
PathChecker

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,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

@@ -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,4 +1,4 @@
= form_with url: bulk_update_admin_products_path, method: :post, id: "products-form",
= form_with url: admin_products_bulk_update_path, method: :post, id: "products-form",
builder: BulkFormBuilder,
html: { data: { 'turbo-frame': "_self",
controller: "bulk-form",

View File

@@ -3,10 +3,7 @@
.pagination{ "data-controller": "search" }
- if pagy.prev
%button.page.prev{ data: { action: 'click->search#changePage', page: pagy.prev } }
- if feature?(:admin_style_v3, spree_current_user)
%i.icon-chevron-left{ data: { action: 'click->search#changePage', page: pagy.prev } }
- else
!= pagy_t('pagy.prev')
%i.icon-chevron-left{ data: { action: 'click->search#changePage', page: pagy.prev } }
- else
%button.page.disabled{disabled: "disabled"}!= pagy_t('pagy.prev')
@@ -22,9 +19,6 @@
- if pagy.next
%button.page.next{ data: { action: 'click->search#changePage', page: pagy.next } }
- if feature?(:admin_style_v3, spree_current_user)
%i.icon-chevron-right{ data: { action: 'click->search#changePage', page: pagy.next } }
- else
!= pagy_t('pagy.next')
%i.icon-chevron-right{ data: { action: 'click->search#changePage', page: pagy.next } }
- else
%button.page.disabled.pagination-next{disabled: "disabled"}!= pagy_t('pagy.next')

View File

@@ -1,7 +1,7 @@
= admin_inject_available_units
- content_for :page_actions do
%li= button_link_to t('admin.products.back_to_products_list'), products_return_to_url(@url_filters), :icon => 'icon-arrow-left'
%li= button_link_to t('admin.products.back_to_products_list'), products_return_to_url, :icon => 'icon-arrow-left'
%li#new_product_link
= button_link_to t(:new_product), new_object_url, { :icon => 'icon-plus', :id => 'admin_new_product' }
@@ -18,6 +18,6 @@
= button t(:update), 'icon-refresh'
= button_link_to t(:cancel), products_return_to_url(@url_filters), icon: 'icon-remove'
= button_link_to t(:cancel), products_return_to_url, icon: 'icon-remove'
#product-preview-modal-container

View File

@@ -1,14 +0,0 @@
= render 'spree/admin/products/index/header'
= render 'spree/admin/products/index/data'
= admin_inject_available_units
%div{ "ng-app": 'ofn.admin', "ng-controller": 'AdminProductEditCtrl', "ng-init": 'initialise()' }
= render 'spree/admin/products/index/filters'
%div{ 'ng-cloak' => true }
= render 'spree/admin/products/index/actions'
= render 'spree/admin/products/index/indicators'
= render 'spree/admin/products/index/products'
%div{'ng-show' => "!RequestMonitor.loading && products.length > 0" }
= render partial: 'admin/shared/angular_pagination'

View File

@@ -1,11 +0,0 @@
.controls.sixteen.columns.alpha{ 'ng-hide' => 'RequestMonitor.loading || products.length == 0' }
.ten.columns.alpha.index-controls
.per-page{'ng-show' => '!RequestMonitor.loading && products.length > 0'}
%input.per-page-select.ofn-select2{type: 'number', data: 'per_page_options', 'min-search' => 999, 'ng-model' => 'per_page', 'ng-change' => 'fetchProducts()'}
%span.per-page-feedback
{{ 'spree.admin.orders.index.results_found' | t:{number: pagination.results} }}
{{ 'spree.admin.orders.index.viewing' | t:{start: ((pagination.page -1) * pagination.per_page) +1, end: ((pagination.page -1) * pagination.per_page) + products.length} }}
.six.columns.omega
%columns-dropdown{ action: "#{controller_name}_#{action_name}" }

View File

@@ -1,5 +0,0 @@
= admin_inject_producers(@producers)
= admin_inject_taxons(@taxons)
= admin_inject_tax_categories(@tax_categories)
= admin_inject_spree_api_key(@spree_api_key)
= admin_inject_column_preferences

View File

@@ -1,33 +0,0 @@
%fieldset
%legend{align: 'center'}= t(:search)
.filters.sixteen.columns.alpha.omega
.quick_search.three.columns.alpha
%label{ for: 'quick_filter' }
%br
%input.quick-search.fullwidth{ name: "quick_filter", type: 'text', placeholder: t('admin.quick_search'), "ng-keypress": "$event.keyCode === 13 && fetchProducts()", "ng-model": 'q.query' }
.one.columns &nbsp;
.filter_select.three.columns
%label{ for: 'producer_filter' }= t 'producer'
%br
%select.fullwidth{ id: 'producer_filter', "ofn-select2-min-search": 5, "ng-model": 'q.producerFilter', "ng-options": 'producer.id as producer.name for producer in producers' }
.filter_select.three.columns
%label{ for: 'category_filter' }= t 'category'
%br
%select.fullwidth{ id: 'category_filter', "ofn-select2-min-search": 5, "ng-model": 'q.categoryFilter', "ng-options": 'taxon.id as taxon.name for taxon in taxons' }
.filter_select.three.columns
%label{ for: 'import_filter' }= t 'import_date'
%br
%select.fullwidth{ id: 'import_date_filter', "ofn-select2-min-search": 5, "ng-model": 'q.importDateFilter', "ng-init": "importDates = #{@import_dates}; showLatestImport = #{@show_latest_import}", "ng-options": 'date.id as date.name for date in importDates' }
.filter_clear.three.columns.omega
%label{ for: 'clear_all_filters' }
%br
%input.fullwidth.red{ :type => 'button', :id => 'clear_all_filters', :value => t('admin.clear_filters'), 'ng-click' => "resetSelectFilters()" }
.clearfix
.actions.filter-actions
%div
%a.button.icon-search{'ng-click' => 'fetchProducts()'}
= t(:filter_results)

View File

@@ -1,10 +0,0 @@
- content_for :page_title do
= t('.title')
- content_for :page_actions do
%div{ :class => "toolbar" }
%ul{ :class => "actions header-action-links inline-menu" }
%li#new_product_link
= button_link_to t(:new_product), new_object_url, { :icon => 'icon-plus', :id => 'admin_new_product' }
= render partial: 'spree/admin/shared/product_sub_menu'

View File

@@ -1,14 +0,0 @@
.sixteen.columns.alpha#loading{ 'ng-if' => 'RequestMonitor.loading' }
= render partial: "components/admin_spinner"
%h1
= t('.title')
.sixteen.columns.alpha{ 'ng-show' => '!RequestMonitor.loading && products.length == 0 && q.query.length == 0' }
%h1#no_results= t('.no_products')
.sixteen.columns.alpha{ 'ng-show' => '!RequestMonitor.loading && products.length == 0 && q.query.length != 0' }
%h1#no_results
= t('.no_results')
'
{{q.query}}
'

View File

@@ -1,14 +0,0 @@
.sixteen.columns.alpha{ 'ng-hide' => 'RequestMonitor.loading || products.length == 0' }
%form{ name: 'bulk_product_form', autocomplete: "off" }
%save-bar{ dirty: "bulk_product_form.$dirty", persist: "false" }
%input.red{ type: "button", value: t(:save_changes), "ng-click": "submitProducts()", "ng-disabled": "!bulk_product_form.$dirty" }
%input{ type: "button", value: t(:close), 'ng-click' => "cancel('#{admin_products_path}')" }
%table.index#listing_products.bulk
= render 'spree/admin/products/index/products_head'
%tbody{ 'ng-repeat' => 'product in products', 'ng-class-even' => "'even'", 'ng-class-odd' => "'odd'" }
= render 'spree/admin/products/index/products_product'
= render 'spree/admin/products/index/products_variant'

View File

@@ -1,41 +0,0 @@
%colgroup
%col.actions
%col.image{ "ng-show": 'columns.image.visible' }
%col.producer{ "ng-show": 'columns.producer.visible' }
%col.sku{ "ng-show": 'columns.sku.visible' }
%col.name{ "ng-show": 'columns.name.visible' }
%col.unit{ "ng-show": 'columns.unit.visible' }
%col.display_as{ "ng-show": 'columns.unit.visible' }
%col.price{ "ng-show": 'columns.price.visible' }
%col.on_hand{ "ng-show": 'columns.on_hand.visible' }
%col.on_demand{ "ng-show": 'columns.on_demand.visible' }
%col.category{ "ng-show": 'columns.category.visible' }
%col.tax_category{ "ng-show": 'columns.tax_category.visible' }
%col.inherits_properties{ "ng-show": 'columns.inherits_properties.visible' }
%col.import_date{ "ng-show": 'columns.import_date.visible' }
%col.actions
%col.actions
%col.actions
%thead
%tr{ "ng-controller": "ColumnsCtrl" }
%th.left-actions
%a{ 'ng-click' => 'toggleShowAllVariants()', :style => 'color: red; cursor: pointer' }
= t(:expand_all)
%th.image{ 'ng-show' => 'columns.image.visible' }
%th.producer{ 'ng-show' => 'columns.producer.visible' }=t('admin.producer')
%th.sku{ 'ng-show' => 'columns.sku.visible' }=t('admin.sku')
%th.name{ 'ng-show' => 'columns.name.visible' }
= render partial: 'spree/admin/shared/sortable_header', locals: {column_name: 'name'}
%th.unit{ 'ng-show' => 'columns.unit.visible' }=t('.unit')
%th.display_as{ 'ng-show' => 'columns.unit.visible' }=t('.display_as')
%th.price{ 'ng-show' => 'columns.price.visible' }=t('admin.price')
%th.on_hand{ 'ng-show' => 'columns.on_hand.visible' }=t('admin.on_hand')
%th.on_demand{ 'ng-show' => 'columns.on_demand.visible' }=t('admin.on_demand?')
%th.category{ 'ng-show' => 'columns.category.visible' }=t('.category')
%th.tax_category{ 'ng-show' => 'columns.tax_category.visible' }=t('.tax_category')
%th.inherits_properties{ 'ng-show' => 'columns.inherits_properties.visible' }=t('.inherits_properties?')
%th.import_date{ 'ng-show' => 'columns.import_date.visible' }=t('.import_date')
%th.actions
%th.actions
%th.actions

View File

@@ -1,33 +0,0 @@
%tr.product{ :id => "p_{{product.id}}" }
%td.left-actions
%a{ 'ofn-toggle-variants' => 'true', :class => "view-variants", 'ng-show' => 'hasVariants(product)' }
%a{ :class => "add-variant icon-plus-sign", 'ng-click' => "addVariant(product)", 'ng-show' => "!hasVariants(product) && hasUnit(product)" }
%td.image{ 'ng-show' => 'columns.image.visible' }
%a{class: 'image-modal'}
%img{'ng-src' => '{{ product.thumb_url }}'}
%td.producer{ 'ng-show' => 'columns.producer.visible' }
%td.sku{ 'ng-show' => 'columns.sku.visible' }
%input{ 'ng-model' => "product.sku", :name => 'product_sku', 'ofn-track-product' => 'sku', :type => 'text' }
%td.name{ 'ng-show' => 'columns.name.visible' }
%input{ 'ng-model' => "product.name", :name => 'product_name', 'ofn-track-product' => 'name', :type => 'text' }
%td.unit{ 'ng-show' => 'columns.unit.visible' }
%td.display_as{ 'ng-show' => 'columns.unit.visible' }
%td.price{ 'ng-show' => 'columns.price.visible' }
%input{ 'ng-model' => 'product.price', 'ofn-decimal' => :true, :name => 'price', 'ofn-track-product' => 'price', :type => 'text', 'ng-hide' => 'hasVariants(product)' }
%td.on_hand{ 'ng-show' => 'columns.on_hand.visible' }
%span{ 'ng-bind' => 'product.on_hand', :name => 'on_hand', 'ng-if' => '!hasOnDemandVariants(product) && (hasVariants(product) || product.on_demand)' }
%input.field{ 'ng-model' => 'product.on_hand', :name => 'on_hand', 'ofn-track-product' => 'on_hand', 'ng-if' => '!(hasVariants(product) || product.on_demand)', :type => 'number' }
%td.on_demand{ 'ng-show' => 'columns.on_demand.visible' }
%input.field{ 'ng-model' => 'product.on_demand', :name => 'on_demand', 'ofn-track-product' => 'on_demand', :type => 'checkbox', 'ng-hide' => 'hasVariants(product)' }
%td.category{ 'ng-if' => 'columns.category.visible' }
%td.tax_category{ 'ng-if' => 'columns.tax_category.visible' }
%td.inherits_properties{ 'ng-show' => 'columns.inherits_properties.visible' }
%input{ 'ng-model' => 'product.inherits_properties', :name => 'inherits_properties', 'ofn-track-product' => 'inherits_properties', type: "checkbox" }
%td.import_date{ 'ng-show' => 'columns.import_date.visible' }
%span {{(product.import_date | date:"MMMM dd, yyyy HH:mm") || ""}}
%td.actions
%a{ 'ng-click' => 'editWarn(product)', :class => "edit-product icon-edit no-text", 'ofn-with-tip' => t(:edit) }
%td.actions
%a{ 'ng-click' => 'cloneProduct(product)', :class => "clone-product icon-copy no-text", 'ofn-with-tip' => t(:clone) }
%td.actions
%a{ 'ng-click' => 'deleteProduct(product)', :class => "delete-product icon-trash no-text", 'ofn-with-tip' => t(:remove) }

View File

@@ -1,39 +0,0 @@
%tr.variant{ :id => "v_{{variant.id}}", 'ng-repeat' => 'variant in product.variants', 'ng-show' => 'DisplayProperties.showVariants(product.id)', 'ng-class-even' => "'even'", 'ng-class-odd' => "'odd'" }
%td.left-actions
%a{ :class => "variant-item icon-caret-right", 'ng-hide' => "$last" }
%a{ :class => "add-variant icon-plus-sign", 'ng-click' => "addVariant(product)", 'ng-show' => "$last", 'ofn-with-tip' => t('.new_variant') }
%td{ 'ng-show' => 'columns.image.visible' }
%td{ 'ng-show' => 'columns.producer.visible' }
%select.fullwidth{ "data-controller": "tom-select", 'ng-model' => 'variant.producer_id', :name => 'producer_id', 'ofn-track-variant' => 'producer_id', 'ng-options' => 'producer.id as producer.name for producer in producers' }
%td{ 'ng-show' => 'columns.sku.visible' }
%input{ 'ng-model' => "variant.sku", :name => 'variant_sku', 'ofn-track-variant' => 'sku', :type => 'text' }
%td{ 'ng-show' => 'columns.name.visible' }
%input{ 'ng-model' => 'variant.display_name', :name => 'variant_display_name', 'ofn-track-variant' => 'display_name', :type => 'text', placeholder: "{{ product.name }}" }
%td.unit_value{ 'ng-show' => 'columns.unit.visible' }
%select.no-search{ "data-controller": "tom-select", 'ng-model' => 'variant.variant_unit_with_scale', :name => 'variant_unit_with_scale', 'ofn-track-variant' => 'variant_unit_with_scale', 'ng-options' => 'unit[1] as unit[0] for unit in variant_unit_options' }
%input{ 'ng-model' => 'variant.unit_value_with_description', :name => 'variant_unit_value_with_description', 'ofn-track-variant' => 'unit_value_with_description', :type => 'text', :placeholder => 'value', 'ng-show' => "hasUnit(variant)" }
%input{ 'ng-model' => 'variant.variant_unit_name', :name => 'variant_unit_name', 'ofn-track-variant' => 'variant_unit_name', :placeholder => 'unit', 'ng-show' => "variant.variant_unit_with_scale == 'items'", :type => 'text' }
%td.display_as{ 'ng-show' => 'columns.unit.visible' }
%input{ 'ofn-display-as' => 'variant', 'ng-model' => 'variant.display_as', name: 'variant_display_as', 'ofn-track-variant' => 'display_as', type: 'text', placeholder: '{{ placeholder_text }}' }
%td{ 'ng-show' => 'columns.price.visible' }
%input{ 'ng-model' => 'variant.price', 'ofn-decimal' => :true, :name => 'variant_price', 'ofn-track-variant' => 'price', :type => 'text' }
%td{ 'ng-show' => 'columns.on_hand.visible' }
%input.field{ 'ng-model' => 'variant.on_hand', 'ng-change' => 'updateOnHand(product)', :name => 'variant_on_hand', 'ng-if' => '!variant.on_demand', 'ofn-track-variant' => 'on_hand', :type => 'number' }
%span{ :name => 'variant_on_hand', 'ng-if' => 'variant.on_demand' }
= t(:on_demand)
%td{ 'ng-show' => 'columns.on_demand.visible' }
%input.field{ 'ng-model' => 'variant.on_demand', :name => 'variant_on_demand', 'ofn-track-variant' => 'on_demand', :type => 'checkbox' }
%td{ 'ng-show' => 'columns.category.visible' }
%input.fullwidth{ type: 'text', id: "p{{product.id}}_category_id", 'ng-model' => 'variant.category_id', 'ofn-taxon-autocomplete' => '', 'ofn-track-variant' => 'category_id', 'multiple-selection' => 'false', placeholder: 'Category' }
%td{ 'ng-show' => 'columns.tax_category.visible' }
%select.select2{ name: 'variant_tax_category_id', "ofn-track-variant": 'tax_category_id', "ng-model": 'variant.tax_category_id', "ng-options": 'tax_category.id as tax_category.name for tax_category in tax_categories' }
%option{ value: '' }= t(:none)
%td{ 'ng-show' => 'columns.inherits_properties.visible' }
%td{ 'ng-show' => 'columns.import_date.visible' }
%span {{variant.import_date | date:"MMMM dd, yyyy HH:mm"}}
%td.actions
%a{ 'ng-click' => 'editWarn(product,variant)', :class => "edit-variant icon-edit no-text", 'ng-show' => "variantSaved(variant)", 'ofn-with-tip' => t(:edit) }
%td.actions
%span.icon-warning-sign{ 'ng-if' => 'variant.variant_overrides_count > 0', 'ofn-with-tip' => "{{ 'spree.admin.products.index.products_variant.variant_has_n_overrides' | t:{n: variant.variant_overrides_count} }}" }
%td.actions
%a{ 'ng-click' => 'deleteVariant(product,variant)', "ng-class" => '{disabled: product.variants.length < 2}', :class => "delete-variant icon-trash no-text", 'ofn-with-tip' => t(:remove) }

View File

@@ -1,3 +0,0 @@
.sixteen.columns.alpha{ 'ng-hide' => 'RequestMonitor.loading || products.length == 0', style: "margin-bottom: 10px" }
.four.columns.alpha
%input.four.columns.alpha{ :type => 'button', :value => t(:save_changes), 'ng-click' => 'submitProducts()'}

View File

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

View File

@@ -1,6 +1,6 @@
- content_for :sub_menu do
%ul#sub_nav.inline-menu
= tab :products, :products_v3
= tab :products, :products_v3, url: admin_products_path
= tab :properties
= tab :variant_overrides, url: main_app.admin_inventory_path, match_path: '/inventory' if feature?(:inventory, spree_current_user.enterprises)
= tab :import, url: main_app.admin_product_import_path, match_path: '/product_import'

View File

@@ -1,11 +1,11 @@
= tab :overview, label: 'dashboard', url: spree.admin_dashboard_path, icon: 'icon-dashboard'
= tab :products, :properties, :inventory, :product_import, :images, :variants, :product_properties, :group_buy_options, :seo, :products_v3, :variant_overrides, url: admin_products_path, icon: 'icon-th-large'
= tab :order_cycles, url: main_app.admin_order_cycles_path, icon: 'icon-refresh'
= tab :orders, :subscriptions, :customer_details, :adjustments, :payments, :return_authorizations, url: admin_orders_path, icon: 'icon-shopping-cart'
= tab :reports, url: main_app.admin_reports_path, icon: 'icon-file'
= tab :general_settings, :terms_of_service_files, :mail_methods, :tax_categories, :tax_rates, :tax_settings, :zones, :countries, :states, :payment_methods, :taxons, :shipping_methods, :shipping_categories, :enterprise_fees, :contents, :invoice_settings, :matomo_settings, :stripe_connect_settings, :connected_app_settings, label: 'configuration', icon: 'icon-wrench', url: edit_admin_general_settings_path
= tab :overview, label: 'dashboard', url: spree.admin_dashboard_path
= tab :products, :properties, :inventory, :product_import, :images, :variants, :product_properties, :group_buy_options, :seo, :products_v3, :variant_overrides, url: admin_products_path
= tab :order_cycles, url: main_app.admin_order_cycles_path
= tab :orders, :subscriptions, :customer_details, :adjustments, :payments, :return_authorizations, url: admin_orders_path
= tab :reports, url: main_app.admin_reports_path
= tab :general_settings, :terms_of_service_files, :mail_methods, :tax_categories, :tax_rates, :tax_settings, :zones, :countries, :states, :payment_methods, :taxons, :shipping_methods, :shipping_categories, :enterprise_fees, :contents, :invoice_settings, :matomo_settings, :stripe_connect_settings, :connected_app_settings, label: 'configuration', url: edit_admin_general_settings_path
= tab :enterprises, :enterprise_relationships, :vouchers, :oidc_settings, url: main_app.admin_enterprises_path
= tab :customers, url: main_app.admin_customers_path
= tab :enterprise_groups, url: main_app.admin_enterprise_groups_path, label: 'groups'
- if can? :admin, Spree::User
= tab(:users, :enterprise_roles, url: spree.admin_users_path, icon: 'icon-user')
= tab(:users, :enterprise_roles, url: spree.admin_users_path)

View File

@@ -1,20 +1,5 @@
// import Flatpickr
import Flatpickr from "stimulus-flatpickr";
import { ar } from "flatpickr/dist/l10n/ar";
import { cat } from "flatpickr/dist/l10n/cat";
import { cy } from "flatpickr/dist/l10n/cy";
import { de } from "flatpickr/dist/l10n/de";
import { fi } from "flatpickr/dist/l10n/fi";
import { fr } from "flatpickr/dist/l10n/fr";
import { it } from "flatpickr/dist/l10n/it";
import { nl } from "flatpickr/dist/l10n/nl";
import { pl } from "flatpickr/dist/l10n/pl";
import { pt } from "flatpickr/dist/l10n/pt";
import { ru } from "flatpickr/dist/l10n/ru";
import { sv } from "flatpickr/dist/l10n/sv";
import { tr } from "flatpickr/dist/l10n/tr";
import { en } from "flatpickr/dist/l10n/default.js";
import { hu } from "flatpickr/dist/l10n/hu";
import ShortcutButtonsPlugin from "shortcut-buttons-flatpickr";
import labelPlugin from "flatpickr/dist/plugins/labelPlugin/labelPlugin";
@@ -24,28 +9,11 @@ export default class extends Flatpickr {
*/
static values = { enableTime: Boolean, mode: String, defaultDate: String };
static targets = ["start", "end"];
locales = {
ar: ar,
cat: cat,
cy: cy,
de: de,
fi: fi,
fr: fr,
it: it,
nl: nl,
pl: pl,
pt: pt,
ru: ru,
sv: sv,
tr: tr,
en: en,
hu: hu,
};
initialize() {
const datetimepicker = this.enableTimeValue === true;
const mode = this.modeValue === "range" ? "range" : "single";
// sets your language (you can also set some global setting for all time pickers)
// configure flatpickr options (locale set dynamically in connect())
this.config = {
altInput: true,
altFormat: datetimepicker
@@ -54,13 +22,18 @@ export default class extends Flatpickr {
dateFormat: datetimepicker ? "Y-m-d H:i" : "Y-m-d",
enableTime: datetimepicker,
time_24hr: datetimepicker,
locale: I18n.base_locale,
plugins: this.plugins(mode, datetimepicker),
mode,
};
}
connect() {
async connect() {
const locale = await this.importFlatpickrLocale(I18n.base_locale);
this.config = {
...this.config,
locale,
};
super.connect();
window.addEventListener("flatpickr:change", this.onChangeEvent);
window.addEventListener("flatpickr:clear", this.clear);
@@ -164,4 +137,16 @@ export default class extends Flatpickr {
this.fp.setDate(moment().add(1, "days").startOf("day").format());
}
}
async importFlatpickrLocale(localeCode) {
// null tells flatpickr to fall back to its built-in english locale
if (!localeCode || localeCode === "en") return null;
try {
const localeModule = await import(`flatpickr/dist/l10n/${localeCode}.js`);
return localeModule.default?.[localeCode] ?? null;
} catch {
return null;
}
}
}

View File

@@ -1,125 +0,0 @@
@import "vendor/assets/stylesheets/normalize";
@import "vendor/assets/stylesheets/responsive-tables";
@import "vendor/assets/stylesheets/jquery.powertip";
@import "~jquery-ui/themes/base/core";
@import "~jquery-ui/themes/base/button";
@import "~jquery-ui/themes/base/resizable";
@import "vendor/assets/stylesheets/jquery-ui-theme";
@import "~jquery-ui/themes/base/dialog";
@import "../shared/ng-tags-input.min";
@import "vendor/assets/stylesheets/select2.css.scss";
@import "~flatpickr/dist/flatpickr";
@import "~flatpickr/dist/themes/material_blue";
@import "~shortcut-buttons-flatpickr/dist/themes/light";
@import "globals/functions";
@import "globals/palette";
@import "globals/variables";
@import "globals/mixins";
@import "plugins/font-awesome";
@import "../shared/variables/layout";
@import "../shared/variables/variables";
@import "../shared/utilities";
@import "shared/typography";
@import "shared/tables";
@import "shared/icons";
@import "shared/forms";
@import "shared/layout";
@import "shared/scroll_bar";
@import "../shared/trix";
@import "plugins/flatpickr-customization";
@import "plugins/powertip";
@import "plugins/select2";
@import "sections/orders";
@import "sections/products";
@import "hacks/mozilla";
@import "hacks/opera";
@import "hacks/ie";
@import "components/actions";
@import "components/alert-box";
@import "components/alert_row";
@import "components/buttons";
@import "components/date-picker";
@import "components/dialogs";
@import "components/input";
@import "components/jquery_dialog";
@import "components/messages";
@import "components/navigation";
@import "components/ng-cloak";
@import "components/page_actions";
@import "components/pagination";
@import "components/per_page_controls";
@import "components/product_autocomplete";
@import "components/progress";
@import "components/save_bar";
@import "components/sidebar";
@import "components/simple_modal";
@import "components/states";
@import "components/stripe_connect_button";
@import "components/subscriptions_states";
@import "components/table-filter";
@import "components/table_loading";
@import "components/timepicker";
@import "components/todo";
@import "components/tooltip";
@import "components/wizard_progress";
@import "pages/enterprise_form";
@import "pages/subscription_form";
@import "pages/subscription_line_items";
@import "pages/subscription_review";
@import "advanced_settings";
@import "alert";
@import "animations";
@import "change_type_form";
@import "connected_apps";
@import "customers";
@import "dashboard_item";
@import "dashboard-single-ent";
@import "dialog";
@import "disabled";
@import "dropdown";
@import "enterprise_index_panels";
@import "enterprises";
@import "filters_and_controls";
@import "grid";
@import "icons";
@import "index_panel_buttons";
@import "index_panels";
@import "modals";
@import "offsets";
@import "openfoodnetwork";
@import "order_cycles";
@import "orders";
@import "product_import";
@import "products";
@import "question-mark-tooltip";
@import "relationships";
@import "reports";
@import "select2";
@import "sidebar-item";
@import "side_menu";
@import "tables";
@import "tag_rules";
@import "terms_of_service_banner";
@import "terms_of_service_files";
@import "validation";
@import "variant_overrides";
@import "welcome";
@import "../shared/question-mark-icon";
@import "question-mark-tooltip";
@import "~tom-select/src/scss/tom-select.default";
@import "components/tom_select";
@import "app/components/modal_component/modal_component";
@import "app/webpacker/css/admin/trix.scss";

View File

@@ -1,31 +0,0 @@
table tbody tr {
&.highlight {
@each $action in $actions {
&.action-#{$action} td {
background-color: get-value($actions, $actions-bg-colors, $action);
border-color: get-value($actions, $actions-brd-colors, $action);
}
}
&.action-remove td,
&.action-void td {
text-decoration: line-through;
&.actions {
text-decoration: none;
}
}
}
&.before-highlight {
@each $action in $actions {
&.action-#{$action} td {
border-bottom-color: get-value($actions, $actions-brd-colors, $action);
}
}
}
td.actions {
background-color: transparent !important;
}
}

View File

@@ -1,93 +0,0 @@
input[type="submit"],
input[type="button"]:not(.trix-button),
button:not(.plain):not(.trix-button),
.button {
position: relative;
cursor: pointer;
font-size: 85%;
@include border-radius($border-radius);
display: inline-block;
padding: 8px 15px;
border: none;
background-color: $color-btn-bg;
color: $color-btn-text;
text-transform: uppercase;
font-weight: 600 !important;
&:before {
font-weight: normal !important;
}
&:visited,
&:active,
&:focus {
color: $color-btn-text;
}
&:hover {
background-color: $color-btn-hover-bg;
color: $color-btn-hover-text;
}
&:active:focus {
box-shadow: 0 0 8px 0 darken($color-btn-hover-bg, 5) inset;
}
&.fullwidth {
width: 100%;
text-align: center;
}
&.secondary {
background-color: transparent;
border: 1px solid $color-btn-bg;
color: $color-btn-bg;
&:hover,
&:active,
&:focus {
background-color: #ebf3fb;
}
&:active:focus {
box-shadow: none;
}
}
.badge {
position: absolute;
top: 0;
right: 0;
transform: translateY(-50%);
font-size: 10px;
text-transform: capitalize;
padding: 0px 5px;
border-radius: 3px;
&:before {
padding: 0;
}
&.danger {
background-color: $color-warning;
}
&.success {
background-color: $spree-green;
}
}
}
input.red,
a.button.red,
button.red {
background-color: $color-warning;
margin-right: 5px;
color: #ffffff;
}
a.button.red {
&:not(:hover) {
color: #fff;
background-color: $color-warning;
}
}

View File

@@ -1,20 +0,0 @@
// scss-lint:disable QualifyingElement
input.datetimepicker {
min-width: 12.9em;
}
.container input[readonly].flatpickr-input,
.container input[readonly].datepicker,
.container input[readonly].datetimepicker {
background-color: $white;
cursor: pointer;
}
img.ui-datepicker-trigger {
margin-left: -1.75em;
position: absolute;
margin-top: 0.5em;
}
// scss-lint:enable QualifyingElement

View File

@@ -1,76 +0,0 @@
.errorExplanation {
padding: 10px;
border: 1px solid very-light($color-error, 12);
background-color: very-light($color-error, 6);
border-radius: 3px;
color: $color-error;
margin-bottom: 15px;
h2 {
font-size: 140%;
color: $color-error;
margin-bottom: 5px;
}
p {
padding: 10px 0;
}
ul {
list-style-position: inside;
li {
font-weight: $font-weight-bold;
}
}
}
.flash-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 1000;
.flash {
padding: 18px;
text-align: center;
font-size: 120%;
color: $color-1;
font-weight: 600;
margin-top: 0;
&.notice {
background-color: rgba($color-notice, 0.8);
}
&.success {
background-color: rgba($color-success, 0.8);
}
&.error {
background-color: rgba($color-error, 0.8);
}
// Adjust heights to fit main layout dimension (header, navbar...)
&:nth-child(2) {
padding: 24px;
}
&:nth-child(3) {
padding: 20px;
}
.actions {
display: none; /* avoid adding new button on old design */
}
}
}
.notice:not(.flash) {
padding: 1rem;
margin-bottom: 1.5rem;
background-color: $spree-light-blue;
border-radius: $border-radius;
a {
font-weight: bold;
}
}

View File

@@ -1,174 +0,0 @@
// Navigation
//---------------------------------------------------
.inline-menu {
margin: 0;
-webkit-margin-before: 0;
-webkit-padding-start: 0;
}
nav.menu {
ul {
list-style: none;
li {
a {
padding: 10px 0;
display: block;
position: relative;
text-align: left;
border: 1px solid transparent;
text-transform: uppercase;
font-weight: 600;
font-size: 90%;
}
&.active a {
color: $color-2;
border-left-width: 0;
border-bottom-color: $color-2;
}
&:hover a {
color: $color-2;
}
}
}
}
.admin-login-navigation-bar {
ul {
text-align: right;
li {
padding: 5px 0 5px 10px;
text-align: right;
font-size: 90%;
color: $color-link;
margin-top: 8px;
&.user-logged-in-as {
width: 50%;
color: $color-body-text;
}
&:hover {
i {
color: $color-2;
}
}
}
}
}
#admin-menu {
background-color: $color-3;
ul {
display: flex;
}
li {
min-width: 90px;
flex-grow: 1;
a {
display: block;
padding: 25px 5px;
color: $color-1 !important;
text-transform: uppercase;
position: relative;
text-align: center;
font-weight: 600;
i {
display: inline;
}
&:hover {
background-color: $color-2;
&:after {
content: "";
position: absolute;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 5px solid $color-2;
bottom: 0px;
margin-bottom: -5px;
left: 50%;
margin-left: -10px;
z-index: 1;
}
}
span.text {
font-weight: 600;
}
}
a::before {
font-weight: normal;
padding-top: 0;
}
.dropdown {
width: 300px;
background-color: $color-3;
width: 200px;
z-index: 100000;
> li {
width: 200px !important;
a:after {
display: none;
}
}
}
&.selected a {
@extend a, :hover;
}
}
}
#sub-menu {
background-color: $color-2;
padding-bottom: 0;
li {
a {
display: block;
padding: 12px 20px;
color: $color-1;
text-align: center;
text-transform: uppercase;
position: relative;
font-size: 85%;
}
&.selected a,
a:hover {
&:after {
content: "";
position: absolute;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 5px solid $color-2;
bottom: 0px;
margin-bottom: -5px;
left: 50%;
margin-left: -10px;
z-index: 0;
}
}
}
}
#header figure {
margin: 0.25em 0;
}
#login-nav {
line-height: 1.75em;
}

View File

@@ -1,32 +0,0 @@
.pagination {
text-align: center;
margin: 2em 0 1em;
padding: 10px 0;
.page {
padding: 5px 8px;
text-align: center;
display: inline-block;
text-align: center;
&.current {
background-color: $color-2;
border-radius: 3px;
color: $color-1;
}
}
button {
margin: 0 0.35em;
&.active {
background-color: darken($spree-blue, 15%);
cursor: default;
}
&.disabled {
background-color: $color-btn-disabled-bg;
cursor: default;
}
}
}

View File

@@ -1,26 +0,0 @@
// Sidebar
//---------------------------------------------------
#sidebar {
overflow: visible;
border-top: 1px solid $color-border;
margin-top: 17px;
.sidebar-title {
color: $color-2;
text-transform: uppercase;
text-align: center;
font-size: 14px;
font-weight: 600;
> span {
display: inline;
background: #fff;
padding: 5px 10px;
position: relative;
top: -14px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
}
}

View File

@@ -1,141 +0,0 @@
.ts-wrapper {
min-height: initial;
}
.ts-wrapper.multi {
.ts-control {
box-shadow: none;
border-color: $pale-blue;
&:focus {
border-color: $spree-green;
}
[data-value] {
text-shadow: none;
background-image: none;
background-repeat: initial;
box-shadow: none;
background-color: $spree-blue;
}
}
.ts-control > div {
border: none;
background-color: $spree-blue;
}
}
.ts-wrapper.plugin-remove_button .item .remove {
font-weight: bold;
}
.ts-dropdown {
margin-top: 0;
.option {
min-height: 2.25em;
display: block;
}
}
.ts-wrapper.single .ts-control,
.ts-dropdown.single {
border-color: $color-tbl-border;
}
.ts-control,
.ts-wrapper.single.input-active .ts-control {
cursor: pointer;
padding: 6px 8px;
outline: 0 !important;
min-height: 2.5em;
}
.ts-wrapper.single .ts-control {
padding-right: 2rem;
}
.ts-wrapper.inline,
.ts-wrapper.inline.input-active {
width: fit-content;
.ts-control {
padding-right: 2rem;
}
}
.ts-wrapper.single .ts-control {
box-shadow: none;
background-image: none;
background-color: $white;
}
.ts-wrapper.primary.focus .ts-control,
.ts-wrapper.primary .ts-control {
background-color: $spree-blue;
border-color: $spree-blue;
color: $white;
&:after {
border-color: $white transparent transparent transparent;
}
}
.ts-wrapper .select-multiple {
cursor: pointer;
}
.ts-wrapper.dropdown-active.primary .ts-control {
background-color: $spree-green;
border-color: $spree-green;
color: $white;
&:after {
border-color: transparent transparent $white transparent;
}
}
.dropdown-input-wrap {
padding: 0.2em;
position: relative;
&:before {
@extend [class^="icon-"];
@extend .icon-search;
position: absolute;
opacity: 0.4;
line-height: 2em;
left: 0.75em;
}
.dropdown-input {
outline: 0;
padding: 4px 6px;
border: 1px solid $spree-green;
border-radius: 0.3em;
padding-left: 1.75em;
}
}
.ts-wrapper.no-search {
.dropdown-input-wrap {
display: none;
}
}
.ts-dropdown .create:hover,
.ts-dropdown #admin-menu li.selected a.create,
#admin-menu li.selected .ts-dropdown a.create,
.ts-dropdown .option:hover,
.ts-dropdown #admin-menu li.selected a.option,
#admin-menu li.selected .ts-dropdown a.option,
.ts-dropdown .active {
background-color: $spree-blue;
color: $white;
}
.ts-dropdown [data-selectable] .highlight {
background: rgba(149, 180, 255, 0.26);
}

View File

@@ -1,156 +0,0 @@
// -------------------------------------------------------------
// Variables used in all other files
//--------------------------------------------------------------
// Fonts
//--------------------------------------------------------------
$base-font-family: "Open Sans", "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
// Colors
//--------------------------------------------------------------
// Body base colors
$color-body-bg: $color-1 !default;
$color-body-text: $color-4 !default;
$color-headers: $color-4 !default;
$color-link: $color-3 !default;
$color-link-hover: $color-2 !default;
$color-link-active: $color-2 !default;
$color-link-focus: $color-2 !default;
$color-link-visited: $color-3 !default;
$color-border: very-light($color-3, 12) !default;
// Basic flash colors
$color-success: $color-2 !default;
$color-notice: $color-6 !default;
$color-warning: $color-5 !default;
$color-error: $color-5 !default;
// Table colors
$color-tbl-odd: $color-1 !default;
$color-tbl-even: very-light($color-3, 4) !default;
$color-tbl-thead: very-light($color-3, 4) !default;
$color-tbl-border: $pale-blue !default;
// Button colors
$color-btn-bg: $color-3 !default;
$color-btn-text: $color-1 !default;
$color-btn-hover-bg: $color-2 !default;
$color-btn-hover-text: $color-1 !default;
$color-btn-disabled-bg: $light-grey !default;
// Actions colors
$color-action-edit-bg: very-light($color-success, 5 ) !default;
$color-action-edit-brd: very-light($color-success, 20 ) !default;
$color-action-clone-bg: very-light($color-notice, 5 ) !default;
$color-action-clone-brd: very-light($color-notice, 15 ) !default;
$color-action-remove-bg: very-light($color-error, 5 ) !default;
$color-action-remove-brd: very-light($color-error, 10 ) !default;
$color-action-void-bg: very-light($color-error, 10 ) !default;
$color-action-void-brd: very-light($color-error, 20 ) !default;
$color-action-cancel-bg: very-light($color-notice, 10 ) !default;
$color-action-cancel-brd: very-light($color-notice, 20 ) !default;
$color-action-capture-bg: very-light($color-success, 5 ) !default;
$color-action-capture-brd: very-light($color-success, 20 ) !default;
$color-action-save-bg: very-light($color-success, 5 ) !default;
$color-action-save-brd: very-light($color-success, 20 ) !default;
$color-action-mail-bg: very-light($color-success, 5 ) !default;
$color-action-mail-brd: very-light($color-success, 20 ) !default;
// Select2 select field colors
$color-sel-bg: $color-3 !default;
$color-sel-text: $color-1 !default;
$color-sel-hover-bg: $color-2 !default;
$color-sel-hover-text: $color-1 !default;
// Text inputs colors
$color-txt-brd: $color-border !default;
$color-txt-text: $color-3 !default;
$color-txt-hover-brd: $color-2 !default;
$vpadding-txt: 7px;
$hpadding-txt: 10px;
// Modal colors
$color-modal-close-btn: $color-5 !default;
$color-modal-close-btn-hover: darken($color-5, 5%) !default;
// States label colors
$color-ste-complete-bg: $color-success !default;
$color-ste-complete-text: $color-1 !default;
$color-ste-completed-bg: $color-success !default;
$color-ste-completed-text: $color-1 !default;
$color-ste-sold-bg: $color-success !default;
$color-ste-sold-text: $color-1 !default;
$color-ste-pending-bg: $color-notice !default;
$color-ste-pending-text: $color-1 !default;
$color-ste-requires_authorization-bg: $color-notice !default;
$color-ste-requires_authorization-text: $color-1 !default;
$color-ste-awaiting_return-bg: $color-notice !default;
$color-ste-awaiting_return-text: $color-1 !default;
$color-ste-returned-bg: $color-notice !default;
$color-ste-returned-text: $color-1 !default;
$color-ste-credit_owed-bg: $color-notice !default;
$color-ste-credit_owed-text: $color-1 !default;
$color-ste-paid-bg: $color-success !default;
$color-ste-paid-text: $color-1 !default;
$color-ste-shipped-bg: $color-success !default;
$color-ste-shipped-text: $color-1 !default;
$color-ste-balance_due-bg: $color-notice !default;
$color-ste-balance_due-text: $color-1 !default;
$color-ste-backorder-bg: $color-notice !default;
$color-ste-backorder-text: $color-1 !default;
$color-ste-none-bg: $color-error !default;
$color-ste-none-text: $color-1 !default;
$color-ste-ready-bg: $color-success !default;
$color-ste-ready-text: $color-1 !default;
$color-ste-void-bg: $color-error !default;
$color-ste-void-text: $color-1 !default;
$color-ste-canceled-bg: $color-error !default;
$color-ste-canceled-text: $color-1 !default;
$color-ste-address-bg: $color-error !default;
$color-ste-address-text: $color-1 !default;
$color-ste-checkout-bg: $color-notice !default;
$color-ste-checkout-text: $color-1 !default;
$color-ste-cart-bg: $color-notice !default;
$color-ste-cart-text: $color-1 !default;
$color-ste-payment-bg: $color-error !default;
$color-ste-payment-text: $color-1 !default;
$color-ste-delivery-bg: $color-success !default;
$color-ste-delivery-text: $color-1 !default;
$color-ste-confirmation-bg: $color-error !default;
$color-ste-confirmation-text: $color-1 !default;
$color-ste-active-bg: $color-success !default;
$color-ste-active-text: $color-1 !default;
$color-ste-inactive-bg: $color-notice !default;
$color-ste-inactive-text: $color-1 !default;
// Available states
$states: completed, complete, sold, pending, awaiting_return, returned, credit_owed, paid, shipped, balance_due, backorder, checkout, cart, address, delivery, payment, confirmation, canceled, ready, void, requires_authorization, active, inactive !default;
$states-bg-colors: $color-ste-completed-bg, $color-ste-complete-bg, $color-ste-sold-bg, $color-ste-pending-bg, $color-ste-awaiting_return-bg, $color-ste-returned-bg, $color-ste-credit_owed-bg, $color-ste-paid-bg, $color-ste-shipped-bg, $color-ste-balance_due-bg, $color-ste-backorder-bg, $color-ste-checkout-bg, $color-ste-cart-bg, $color-ste-address-bg, $color-ste-delivery-bg, $color-ste-payment-bg, $color-ste-confirmation-bg, $color-ste-canceled-bg, $color-ste-ready-bg, $color-ste-void-bg, $color-ste-requires_authorization-bg, $color-ste-active-bg, $color-ste-inactive-bg !default;
$states-text-colors: $color-ste-completed-text, $color-ste-complete-text, $color-ste-sold-text, $color-ste-pending-text, $color-ste-awaiting_return-text, $color-ste-returned-text, $color-ste-credit_owed-text, $color-ste-paid-text, $color-ste-shipped-text, $color-ste-balance_due-text, $color-ste-backorder-text, $color-ste-checkout-text, $color-ste-cart-text, $color-ste-address-text, $color-ste-delivery-text, $color-ste-payment-text, $color-ste-confirmation-text, $color-ste-canceled-text, $color-ste-ready-text, $color-ste-void-text, $color-ste-requires_authorization-text, $color-ste-active-text, $color-ste-inactive-text !default;
// Available actions
$actions: edit, clone, remove, void, capture, save, cancel, mail !default;
$actions-bg-colors: $color-action-edit-bg, $color-action-clone-bg, $color-action-remove-bg, $color-action-void-bg, $color-action-capture-bg, $color-action-save-bg, $color-action-cancel-bg, $color-action-mail-bg !default;
$actions-brd-colors: $color-action-edit-brd, $color-action-clone-brd, $color-action-remove-brd, $color-action-void-brd, $color-action-capture-brd, $color-action-save-brd, $color-action-cancel-brd, $color-action-mail-brd !default;
// Sizes
//--------------------------------------------------------------
$body-font-size: 13px !default;
$h6-size: $body-font-size + 2 !default;
$h5-size: $h6-size + 2 !default;
$h4-size: $h5-size + 2 !default;
$h3-size: $h4-size + 2 !default;
$h2-size: $h3-size + 2 !default;
$h1-size: $h2-size + 2 !default;
$border-radius: 3px !default;
$border-input: 1px solid #2e3132; // Copied over from admin_v3 variables as a temporary solution
$font-weight-bold: 600 !default;
$font-weight-normal: 400 !default;
// z-index
//--------------------------------------------------------------
$tos-banner-z-index: 102;

View File

@@ -1,68 +0,0 @@
$background-grey: #eceef1;
$background-blue: $color-3;
// scss-lint:disable SelectorFormat
.flatpickr-calendar {
border-radius: 0;
// Disable animation
&.animate.open {
animation: none;
}
&.arrowBottom::after {
border-top-color: $background-grey;
}
&.arrowTop::after {
border-bottom-color: $background-blue;
}
.flatpickr-months .flatpickr-month {
border-radius: 0;
}
.flatpickr-months .flatpickr-month,
.flatpickr-current-month .flatpickr-monthDropdown-months {
background: $background-blue;
}
.flatpickr-weekdays {
background: $background-blue;
.flatpickr-weekday {
background: $background-blue;
}
}
.flatpickr-day.selected,
.flatpickr-day.startRange,
.flatpickr-day.endRange,
.flatpickr-day.selected.inRange,
.flatpickr-day.startRange.inRange,
.flatpickr-day.endRange.inRange,
.flatpickr-day.selected:focus,
.flatpickr-day.startRange:focus,
.flatpickr-day.endRange:focus,
.flatpickr-day.selected:hover,
.flatpickr-day.startRange:hover,
.flatpickr-day.endRange:hover,
.flatpickr-day.selected.prevMonthDay,
.flatpickr-day.startRange.prevMonthDay,
.flatpickr-day.endRange.prevMonthDay,
.flatpickr-day.selected.nextMonthDay,
.flatpickr-day.startRange.nextMonthDay,
.flatpickr-day.endRange.nextMonthDay {
background: $background-blue;
border-color: $background-blue;
}
}
// scss-lint:enable SelectorFormat
// customization for shortcut-buttons
.shortcut-buttons-flatpickr-wrapper > .shortcut-buttons-flatpickr-buttons {
justify-content: space-between;
flex-grow: 1;
}

View File

@@ -1,118 +0,0 @@
#powerTip {
background-color: $color-3;
padding: 5px 15px;
@include border-radius($border-radius);
&.n:before,
&.ne:before,
&.nw:before {
border-top-width: 5px;
border-top-color: $color-3;
bottom: -5px;
}
&.e:before {
border-right-width: 5px;
border-right-color: $color-3;
left: -5px;
}
&.s:before,
&.se:before,
&.sw:before {
border-bottom-width: 5px;
border-bottom-color: $color-3;
top: -5px;
}
&.w:before {
border-left-width: 5px;
border-left-color: $color-3;
right: -5px;
}
&.ne:before,
&.se:before {
border-right-width: 5px;
border-right-color: $color-3;
left: -5px;
}
&.nw:before,
&.sw:before {
border-left-width: 5px;
border-right-color: $color-3;
right: -5px;
}
&.clone,
&.yellow,
&.cancel {
background-color: $color-notice;
&.n:before,
&.ne:before,
&.nw:before {
border-top-color: $color-notice;
}
&.e:before,
&.nw:before,
&.sw:before {
border-right-color: $color-notice;
}
&.s:before,
&.se:before,
&.sw:before {
border-bottom-color: $color-notice;
}
&.w:before {
border-left-color: $color-notice;
}
}
&.edit,
&.green,
&.capture,
&.save,
&.add {
background-color: $color-success;
&.n:before,
&.ne:before,
&.nw:before {
border-top-color: $color-success;
}
&.e:before,
&.nw:before,
&.sw:before {
border-right-color: $color-success;
}
&.s:before,
&.se:before,
&.sw:before {
border-bottom-color: $color-success;
}
&.w:before {
border-left-color: $color-success;
}
}
&.remove,
&.red,
&.void {
background-color: $color-error;
&.n:before,
&.ne:before,
&.nw:before {
border-top-color: $color-error;
}
&.e:before,
&.nw:before,
&.sw:before {
border-right-color: $color-error;
}
&.s:before,
&.se:before,
&.sw:before {
border-bottom-color: $color-error;
}
&.w:before {
border-left-color: $color-error;
}
}
}

View File

@@ -1,65 +0,0 @@
// Customize orders filter
.admin-orders-index-search {
select[data-placeholder="Status"] {
width: 100%;
}
.select2-container {
width: 100% !important;
}
}
// Order-total
.order-details-total {
text-align: center;
.order-total {
font-size: 35px;
font-weight: 600;
color: $color-success;
}
}
.admin-order-form-fields {
legend.stock-location {
color: $color-body-text;
.shipment-number {
color: $color-success;
}
.stock-location-name {
color: $color-success;
}
}
}
.insufficient-stock-items {
legend {
color: $color-error;
}
table tr:last-child th {
border-bottom: 1px solid $color-tbl-border;
}
}
// Customize orduct add fieldset
#add-line-item {
fieldset {
padding: 10px 0;
.field {
margin-bottom: 0;
input[type="text"],
input[type="number"] {
width: 100%;
}
}
.actions {
.button {
margin-top: 28px;
}
}
}
}

View File

@@ -1,261 +0,0 @@
$text-inputs: "input[type=text], input[type=password], input[type=email], input[type=url], input[type=tel]";
#{$text-inputs},
input[type="date"],
input[type="datetime"],
input[type="time"],
input[type="number"],
textarea,
fieldset {
@include border-radius($border-radius);
padding: $vpadding-txt $hpadding-txt;
border: 1px solid $color-txt-brd;
color: $color-txt-text;
font-size: 90%;
&:focus {
outline: none;
border-color: $color-txt-hover-brd;
}
&[disabled] {
opacity: 0.7;
}
}
textarea {
line-height: 19px;
}
.fullwidth {
width: 100%;
}
label {
font-weight: 600;
text-transform: uppercase;
font-size: 85%;
display: inline;
margin-bottom: 5px;
color: $color-4;
&.inline {
display: inline-block !important;
}
&.block {
display: block !important;
}
}
.label-block label {
display: block;
}
span.info {
font-style: italic;
font-size: 85%;
color: lighten($color-body-text, 15);
display: block;
line-height: 20px;
margin: 5px 0;
}
.field {
padding: 10px 0;
&.checkbox {
min-height: 70px;
input[type="checkbox"] {
display: inline-block;
width: auto;
}
label {
cursor: pointer;
display: block;
}
}
ul {
border-top: 1px solid $color-border;
list-style: none;
padding-top: 5px;
li {
display: inline-block;
padding-right: 10px;
label {
font-weight: normal;
text-transform: none;
}
&.white-space-nowrap {
white-space: nowrap;
}
}
}
// Errors described by default form builder
.field_with_errors {
label {
color: $color-error;
}
input {
border-color: $color-error;
}
}
// Errors described by Spree::Admin::BaseHelper
.formError {
color: $color-error;
font-style: italic;
font-size: 85%;
}
}
fieldset {
box-shadow: none;
box-sizing: border-box;
border-color: $color-border;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
margin-left: 0;
margin-right: 0;
position: relative;
margin-bottom: 35px;
padding: 10px 0 15px 0;
background-color: transparent;
border-left: none;
border-right: none;
border-radius: 0;
&.no-border-bottom {
border-bottom: none;
margin-bottom: 0;
}
&.no-border-top {
border-top: none;
padding-top: 0;
}
legend {
background-color: $color-1;
color: $color-2;
font-size: 14px;
font-weight: 600;
text-transform: uppercase;
text-align: center;
padding: 8px 15px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
i {
color: $color-link;
}
}
label {
color: lighten($color-body-text, 8);
}
.filter-actions {
margin-bottom: -32px;
margin-top: 15px;
text-align: center;
form {
display: inline-block;
}
button,
.button,
input[type="submit"],
input[type="button"],
span.or {
@include border-radius($border-radius);
-webkit-box-shadow: 0 0 0 15px $color-1;
-moz-box-shadow: 0 0 0 15px $color-1;
-ms-box-shadow: 0 0 0 15px $color-1;
-o-box-shadow: 0 0 0 15px $color-1;
box-shadow: 0 0 0 15px $color-1;
&:hover {
border-color: $color-1;
}
&:first-of-type {
margin-right: 1.25em;
}
}
span.or {
background-color: $color-1;
border-width: 5px;
margin-left: 5px;
margin-right: 5px;
position: relative;
-webkit-box-shadow: 0 0 0 5px $color-1;
-moz-box-shadow: 0 0 0 5px $color-1;
-ms-box-shadow: 0 0 0 5px $color-1;
-o-box-shadow: 0 0 0 5px $color-1;
box-shadow: 0 0 0 5px $color-1;
}
}
&.labels-inline {
.field {
margin-bottom: 0;
display: table;
width: 100%;
label,
input {
display: table-cell !important;
}
input {
width: 100%;
}
&.checkbox {
input {
width: auto !important;
}
}
}
.actions {
padding: 0;
text-align: right;
}
}
}
.form-buttons {
text-align: center;
}
select {
@extend input, [type="text"];
background-color: white;
}
.inline-checkbox {
display: inline-flex;
align-items: center;
margin-top: 3px;
input,
label {
cursor: pointer;
}
label {
margin: 0;
padding-left: 0.4rem;
}
}

View File

@@ -1,25 +0,0 @@
// Some fixes for fontwesome stylesheets
[class^="icon-"], [class*=" icon-"] {
&:before {
padding-right: 5px;
}
&.button, &.icon_link {
width: auto;
&:before {
padding-top: 3px;
}
}
}
.icon-email:before { @extend .icon-envelope, :before; }
.icon-resend_authorization_email:before { @extend .icon-envelope, :before; }
.icon-resume:before { @extend .icon-refresh, :before; }
.icon-cancel:before,
.icon-void:before { @extend .icon-remove, :before; }
.icon-capture,
.icon-capture_and_complete_order { @extend .icon-ok }
.icon-credit:before { @extend .icon-ok, :before ; }

View File

@@ -1,134 +0,0 @@
// Basics
//---------------------------------------------------
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.admin {
&__section-header {
padding: 15px 0;
background-color: very-light($color-3, 4);
border-bottom: 1px solid $color-border;
.ofn-drop-down {
border: 0;
background-color: $spree-blue;
color: $color-1;
float: none;
margin-left: 3px;
&:hover,
&.expanded {
border: 0;
color: $color-1;
}
}
&__content {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
@media all and (min-width: $tablet_breakpoint) {
flex-wrap: nowrap;
}
}
&__title {
width: 100%;
margin-bottom: 10px;
@media all and (min-width: $tablet_breakpoint) {
margin-bottom: 0;
}
}
&__actions {
display: flex;
flex: 1 0 auto;
align-items: center;
list-style: none;
@media all and (min-width: $tablet_breakpoint) {
justify-content: flex-end;
}
> li {
display: flex;
margin-right: 10px;
&:empty {
display: none;
}
&:last-child {
margin-right: 0;
}
}
}
}
}
.hidden {
display: none;
}
.float-right {
float: right;
}
.float-left {
float: left;
}
.mr-0 {
margin-right: 0 !important;
}
.ml-0 {
margin-left: 0 !important;
}
@media print {
.print-hidden {
display: none !important;
}
}
// Header
//---------------------------------------------------
#header {
background-color: $color-1;
padding: 5px 0;
}
#logo {
height: 40px;
}
.page-title {
i {
color: $color-2;
}
}
// Content
//---------------------------------------------------
#content {
background-color: $color-1;
position: relative;
z-index: 0;
padding: 0;
margin-top: 15px;
}
// Footer
//---------------------------------------------------
#footer {
margin-top: 15px;
border-top: 1px solid $color-border;
padding: 10px 0;
}
@media print {
header,
nav {
display: none;
}
}

View File

@@ -1,208 +0,0 @@
table {
width: 100%;
margin-bottom: 15px;
border-collapse: separate;
th, td {
padding: 7px 5px;
border-right: 1px solid $color-border;
border-bottom: 1px solid $color-border;
vertical-align: middle;
text-overflow: ellipsis;
img {
border: 1px solid transparent;
}
&:first-child {
border-left: 1px solid $color-border;
}
a {
border-bottom: 1px dotted lighten($color-link, 10);
&:hover {
border-color: lighten($color-link-hover, 10);
}
}
.handle {
display: block !important;
text-align: center;
padding-right: 0;
}
&.actions {
background-color: transparent;
border: none !important;
text-align: center;
span.text {
font-size: $body-font-size;
}
[class*='icon-'].no-text {
font-size: 120%;
background-color: very-light($color-3);
border: 1px solid $color-border;
border-radius: 15px;
width: 29px;
height: 29px;
display: inline-block;
padding-top: 2px;
&:before {
text-align: center !important;
width: 27px;
display: inline-block;
}
&:hover {
border-color: transparent;
}
}
button[class*='icon-'] {
color: $color-link;
padding: 0 !important;
}
.icon-envelope-alt, .icon-eye-open {
color: $color-link;
padding-left: 0px;
&:hover {
background-color: $color-3;
color: $color-1;
}
}
.icon-trash:hover, .icon-void:hover {
background-color: $color-error;
color: $color-1;
}
.icon-cancel:hover {
background-color: $color-notice;
color: $color-1;
}
.icon-edit:hover, .icon-capture:hover, .icon-capture_and_complete_order:hover, .icon-ok:hover, .icon-plus:hover, .icon-road:hover {
background-color: $color-success;
color: $color-1;
}
.icon-copy:hover {
background-color: $color-notice;
color: $color-1;
}
}
input[type="number"],
input[type="text"] {
width: 100%;
}
&.no-border {
border-right: none;
}
.handle {
@extend .icon-reorder;
font-family: FontAwesome;
text-decoration: inherit;
display: inline-block;
speak: none;
cursor: move;
}
}
&.no-borders {
td, th {
border: none !important;
}
}
thead {
th {
padding: 10px;
border-top: 1px solid $color-border;
border-bottom: none;
background-color: $color-tbl-thead;
text-transform: uppercase;
font-size: 85%;
font-weight: $font-weight-bold;
}
}
tbody {
tr {
&:first-child th,
&:first-child td {
border-top: 1px solid $color-border;
}
&.even td {
background-color: $color-tbl-even;
img {
border: 1px solid very-light($color-3, 6);
}
}
&:hover td {
background-color: very-light($color-3, 5);
img {
border: 1px solid $color-border;
}
}
&.deleted td {
background-color: very-light($color-error, 6);
border-color: very-light($color-error, 15);
}
&.ui-sortable-placeholder td {
border: 1px solid $color-2 !important;
visibility: visible !important;
&.actions {
background-color: transparent;
border-right: none !important;
border-top: none !important;
border-bottom: none !important;
border-left: 1px solid $color-2 !important;
}
}
&.ui-sortable-helper {
width: 100%;
td {
background-color: lighten($color-3, 33);
border-bottom: 1px solid $color-border;
&.actions {
display: none;
}
}
}
}
&.no-border-top tr:first-child td {
border-top: none;
}
&.grand-total {
td {
border-color: $color-2 !important;
text-transform: uppercase;
font-size: 110%;
font-weight: 600;
background-color: lighten($color-2, 50);
}
.total {
background-color: $color-2;
color: $color-1;
}
}
}
}

View File

@@ -1,158 +0,0 @@
// Base
//--------------------------------------------------------------
body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, form, p, blockquote, th, td { margin: 0; padding: 0; font-size: $body-font-size; }
body {
font-family: $base-font-family;
font-size: $body-font-size;
font-weight: 400;
color: $color-body-text;
text-rendering: optimizeLegibility;
}
hr {
border-top: 1px solid $color-border;
border-bottom: 1px solid white;
border-left: none;
}
strong, b {
font-weight: 600;
}
// links
//--------------------------------------------------------------
a {
color: $color-link;
text-decoration: none;
line-height: inherit;
&, &:hover, &:active, &:visited, &:focus {
outline: none;
}
&:visited {
color: $color-link-visited;
}
&:focus {
color: $color-link-focus;
}
&:active {
color: $color-link-active;
}
&:hover {
color: $color-link-hover;
}
}
// Headings
//--------------------------------------------------------------
h1,h2,h3,h4,h5,h6 {
font-weight: 600;
color: $color-headers;
line-height: 1.1;
}
h1 { font-size: $h1-size; line-height: $h1-size + 6 }
h2 { font-size: $h2-size; line-height: $h1-size + 4 }
h3 { font-size: $h3-size; line-height: $h1-size + 2 }
h4 { font-size: $h4-size; line-height: $h1-size }
h5 { font-size: $h5-size; line-height: $h1-size }
h6 { font-size: $h6-size; line-height: $h1-size }
// Lists
//--------------------------------------------------------------
ul {
&.inline-menu {
li {
display: inline-block;
}
}
&.fields {
list-style: none;
padding: 0;
margin: 0;
}
}
dl {
width: 100%;
overflow: hidden;
margin: 5px 0;
color: lighten($color-body-text, 15);
dt, dd {
float: left;
line-height: 16px;
padding: 5px;
text-align: justify;
}
dt {
width: 40%;
font-weight: 600;
padding-left: 0;
text-transform: uppercase;
font-size: 85%;
}
dd {
width: 60%;
padding-right: 0;
}
dd:after {
content: '';
clear: both;
}
}
// Helpers
.align-center { text-align: center }
.align-right { text-align: right }
.align-left { text-align: left }
.align-justify { text-align: justify }
.uppercase { text-transform: uppercase }
.green { color: $color-2 }
.blue { color: $color-3 }
.red { color: $color-5 }
.yellow { color: $color-6 }
.no-objects-found {
text-align: center;
font-size: 120%;
text-transform: uppercase;
padding: 40px 0px;
color: lighten($color-body-text, 15);
}
.text-normal {
font-size: 1rem;
font-weight: 300;
}
.text-big {
font-size: 1.2rem;
font-weight: 300;
}
.text-red {
color: $color-warning;
}
input.text-big {
font-size: 1.1rem;
}
.pad-top {
padding-top: 1em;
}
.white-space-nowrap {
white-space: nowrap;
}

View File

@@ -1,27 +0,0 @@
#banner-container {
position: fixed;
bottom: 0px;
left: 0;
width: 100%;
z-index: $tos-banner-z-index;
.terms-of-service-banner {
padding: 18px;
text-align: center;
font-size: 120%;
color: white;
font-weight: 600;
margin-top: 0;
background-color: rgba($color-notice, 0.8);
display: flex;
.column-left {
width: 70%;
}
.column-right {
width: 30%;
text-align: center;
}
}
}

View File

@@ -1,2 +0,0 @@
@import "../css/admin/all.scss";
@import "../../../node_modules/trix/dist/trix.css";

View File

@@ -5,20 +5,36 @@ services:
environment:
POSTGRES_PASSWORD: f00d
POSTGRES_USER: ofn
POSTGRES_DB: open_food_network_dev
ports:
- 5432:5432
volumes:
- 'postgres:/var/lib/postgresql/data'
healthcheck:
test: ["CMD-SHELL", "PGPASSWORD=$$POSTGRES_PASSWORD pg_isready -q -h 127.0.0.1 -p 5432 -U $$POSTGRES_USER || exit 1"]
interval: 5s
timeout: 10s
retries: 10
redis:
image: redis
bundler:
build: .
# Runs once: installs gems into /bundles, writes a checksum sentinel, then exits
command: >
sh -lc 'bundle install --jobs 4 --retry 3 --quiet;
sha256sum Gemfile.lock > /bundles/.Gemfile.lock.sha'
volumes:
- .:/usr/src/app
- gems:/bundles
restart: "no"
web:
tty: true
stdin_open: true
build: .
ports:
- 3000:3000
- 3035:3035
volumes:
- .:/usr/src/app
- gems:/bundles
@@ -26,20 +42,69 @@ services:
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
depends_on:
- db
- redis
db:
condition: service_healthy
redis:
condition: service_started
webpack:
condition: service_started
environment:
DOCKER: true
DEV_CACHING: true
OFN_DB_HOST: db
OFN_REDIS_URL: redis://redis/
OFN_REDIS_JOBS_URL: redis://redis
OFN_REDIS_TEST_URL: redis://redis/3
WEBPACKER_DEV_SERVER_HOST: webpack
WEBPACKER_DEV_SERVER_PORT: 3035
WEBPACKER_DEV_SERVER_PUBLIC: localhost:3035
command: >
bash -c "rm -f tmp/pids/server.pid &&
(bundle check || bundle install) &&
bundle exec rake db:create &&
yarn install &&
bundle exec foreman start -f Procfile.docker"
sh -lc 'rm -f tmp/pids/server.pid;
until [ -f /bundles/.Gemfile.lock.sha ] && sha256sum -c /bundles/.Gemfile.lock.sha >/dev/null 2>&1; do sleep 0.5; done;
bundle exec rails db:prepare &&
yarn install &&
exec bundle exec rails s -b 0.0.0.0 -p 3000'
sidekiq:
build: .
command: >
sh -lc 'until [ -f /bundles/.Gemfile.lock.sha ] && sha256sum -c /bundles/.Gemfile.lock.sha >/dev/null 2>&1; do sleep 0.5; done;
exec bundle exec sidekiq'
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
volumes:
- .:/usr/src/app
- gems:/bundles
environment:
DOCKER: true
DEV_CACHING: true
OFN_DB_HOST: db
OFN_REDIS_URL: redis://redis/
OFN_REDIS_JOBS_URL: redis://redis
OFN_REDIS_TEST_URL: redis://redis/3
webpack:
build: .
command: >
sh -lc 'until [ -f /bundles/.Gemfile.lock.sha ] && sha256sum -c /bundles/.Gemfile.lock.sha >/dev/null 2>&1; do sleep 0.5; done;
exec ./bin/webpack-dev-server'
ports:
- "3035:3035"
volumes:
- .:/usr/src/app
- gems:/bundles
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:3035/webpack-dev-server >/dev/null || wget -qO- http://localhost:3035/sockjs-node/info >/dev/null"]
interval: 5s
timeout: 3s
retries: 30
environment:
WEBPACKER_DEV_SERVER_HOST: 0.0.0.0
volumes:
gems:
postgres:

View File

@@ -1,24 +1,19 @@
require_relative 'boot'
require_relative "boot"
require "rails"
[
"active_record/railtie",
"active_storage/engine",
"action_controller/railtie",
"action_view/railtie",
"action_mailer/railtie",
"active_job/railtie",
"action_cable/engine",
# "action_mailbox/engine",
# "action_text/engine",
"rails/test_unit/railtie",
"sprockets/railtie" # Disable this after migrating to Webpacker
].each do |railtie|
begin
require railtie
rescue LoadError
end
end
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "active_storage/engine"
require "action_controller/railtie"
require "action_mailer/railtie"
# require "action_mailbox/engine"
# require "action_text/engine"
require "action_view/railtie"
require "action_cable/engine"
require "rails/test_unit/railtie"
require "sprockets/railtie" # Disable this after migrating to Webpacker
require_relative "../lib/open_food_network/i18n_config"
require_relative '../lib/spree/core/environment'
@@ -26,15 +21,34 @@ require_relative '../lib/spree/core/mail_interceptor'
require_relative "../lib/i18n_digests"
require_relative "../lib/git_utils"
if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
Bundler.require(*Rails.groups(:assets => %w(development test)))
# If you want your assets lazily compiled in production, use this line
# Bundler.require(:default, :assets, Rails.env)
end
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups(:assets => %w(development test)))
module Openfoodnetwork
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 6.1
config.action_view.form_with_generates_remote_forms = false
config.active_record.cache_versioning = false
config.active_record.has_many_inversing = false
config.active_record.yaml_column_permitted_classes = [BigDecimal, Symbol, Time,
ActiveSupport::TimeWithZone,
ActiveSupport::TimeZone]
# Please, add to the `ignore` list any other `lib` subdirectories that do
# not contain `.rb` files, or that should not be reloaded or eager loaded.
# Common ones are `templates`, `generators`, or `middleware`, for example.
# config.autoload_lib(ignore: %w(assets tasks))
# Configuration for the application, engines, and railties goes here.
#
# These settings can be overridden in specific environments using the files
# in config/environments, which are processed later.
#
config.time_zone = ENV["TIMEZONE"]
# config.eager_load_paths << Rails.root.join("extras")
# Store a description of the current version
config.x.git_version = GitUtils::git_version
@@ -71,16 +85,6 @@ module Openfoodnetwork
end
end
# filter sensitive information during logging
initializer "spree.params.filter" do |app|
app.config.filter_parameters += [
:password,
:password_confirmation,
:number,
:verification_value
]
end
initializer "load_spree_calculators" do |app|
# Register Spree calculators
Rails.application.reloader.to_prepare do
@@ -161,10 +165,6 @@ module Openfoodnetwork
# Activate observers that should always be running.
# config.active_record.observers = :cacher, :garbage_collector, :forum_observer
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
config.time_zone = ENV["TIMEZONE"]
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
config.i18n.default_locale = OpenFoodNetwork::I18nConfig.default_locale
@@ -184,38 +184,14 @@ module Openfoodnetwork
# Enable the asset pipeline
config.assets.enabled = true
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.2'
config.assets.initialize_on_precompile = true
# Unset X-Frame-Options header for embedded pages.
config.action_dispatch.default_headers.except! "X-Frame-Options"
# css and js files other than application.* are not precompiled by default
# Instead, they must be explicitly included below
# http://stackoverflow.com/questions/8012434/what-is-the-purpose-of-config-assets-precompile
config.assets.initialize_on_precompile = true
config.assets.precompile += ['admin/*.js', 'admin/**/*.js', 'admin_minimal.js']
config.assets.precompile += ['web/all.js']
config.assets.precompile += ['darkswarm/all.js']
config.assets.precompile += ['shared/*']
config.assets.precompile += ['mail.scss']
config.assets.precompile += ['*.jpg', '*.jpeg', '*.png', '*.gif' '*.svg']
# Highlight code that triggered database queries in logs.
config.active_record.verbose_query_logs = ENV.fetch("VERBOSE_QUERY_LOGS", false)
# Apply framework defaults. New recommended defaults are successively added with each Rails version and
# include the defaults from previous versions. For more info see:
# https://guides.rubyonrails.org/configuring.html#results-of-config-load-defaults
config.load_defaults 6.1
config.action_view.form_with_generates_remote_forms = false
config.active_record.cache_versioning = false
config.active_record.has_many_inversing = false
config.active_record.yaml_column_permitted_classes = [BigDecimal, Symbol, Time,
ActiveSupport::TimeWithZone,
ActiveSupport::TimeZone]
config.active_support.escape_html_entities_in_json = true
config.active_job.queue_adapter = :sidekiq

View File

@@ -1,7 +1,4 @@
require 'rubygems'
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
# Set up gems listed in the Gemfile.
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
require 'bootsnap/setup'
require "bundler/setup" # Set up gems listed in the Gemfile.
require "bootsnap/setup" # Speed up boot time by caching expensive operations.

View File

@@ -1,7 +1,5 @@
# Load the rails application
require_relative 'application'
# Load the Rails application.
require_relative "application"
# Initialize the rails application
Openfoodnetwork::Application.initialize!
ActiveRecord::Base.include_root_in_json = true
# Initialize the Rails application.
Rails.application.initialize!

View File

@@ -1,40 +1,87 @@
Openfoodnetwork::Application.configure do
config.action_controller.default_url_options = {host: "localhost", port: 3000}
# Settings specified here will take precedence over those in config/application.rb
#
require "active_support/core_ext/integer/time"
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# PROFILE switches several settings to a more "production-like" value
# for profiling and benchmarking the application locally. All changes you
# make to the app will require restart.
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# In the development environment your application's code is reloaded any time
# it changes. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = !!ENV["PROFILE"]
config.action_controller.default_url_options = {host: "localhost", port: 3000}
# Do not eager load code on boot.
config.eager_load = false
# Show full error reports.
config.consider_all_requests_local = true
# Enable server timing
config.server_timing = true
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
#
# To override this, set the appropriate locale in .env[.*] file.
config.time_zone = ENV.fetch("TIMEZONE", "UTC")
config.log_level = ENV.fetch("DEV_LOG_LEVEL", :debug)
# Enable/disable caching. By default caching is disabled.
# Run rails dev:cache to toggle caching.
if Rails.root.join("tmp/caching-dev.txt").exist? || !ENV["PROFILE"] || !!ENV["DEV_CACHING"]
config.action_controller.perform_caching = true
config.action_controller.enable_fragment_cache_logging = true
# :file_store is used by default when no cache store is specifically configured.
if !!ENV["PROFILE"] || !!ENV["DEV_CACHING"]
config.cache_store = :redis_cache_store, {
url: ENV.fetch("OFN_REDIS_URL", "redis://localhost:6379/1"),
expires_in: 90.minutes
}
config.public_file_server.headers = {
"Cache-Control" => "public, max-age=#{2.days.to_i}"
}
else
config.action_controller.perform_caching = false
config.cache_store = :null_store
end
config.eager_load = false
config.action_controller.default_url_options = {host: "localhost", port: 3000}
# Show full error reports and disable caching
config.consider_all_requests_local = true
config.action_controller.perform_caching = !!ENV["PROFILE"] || !!ENV["DEV_CACHING"]
# Store uploaded files on the local file system (see config/storage.yml for options).
# config.active_storage.service = :local
# Don't care if the mailer can't send
# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false
# Print deprecation notices to the Rails logger
config.action_mailer.perform_caching = false
# Show emails using Letter Opener
config.action_mailer.delivery_method = :letter_opener
config.action_mailer.default_url_options = { host: "localhost:3000" }
# Print deprecation notices to the Rails logger.
config.active_support.deprecation = :log
# Only use best-standards-support built into browsers
config.action_dispatch.best_standards_support = :builtin
# Raise exceptions for disallowed deprecations.
config.active_support.disallowed_deprecation = :raise
# Tell Active Support which deprecation messages to disallow.
config.active_support.disallowed_deprecation_warnings = []
# Raise an error on page load if there are pending migrations.
config.active_record.migration_error = :page_load
# Highlight code that triggered database queries in logs.
config.active_record.verbose_query_logs = true
# Highlight code that enqueued background job in logs.
config.active_job.verbose_enqueue_logs = true
# Suppress logger output for asset requests.
config.assets.quiet = true
# Do not compress assets
config.assets.compress = false
@@ -59,17 +106,17 @@ Openfoodnetwork::Application.configure do
# $ bundle exec rake assets:clean
config.assets.debug = !!ENV["DEBUG_ASSETS"]
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
#
# To override this, set the appropriate locale in .env[.*] file.
config.time_zone = ENV.fetch("TIMEZONE", "UTC")
# Raises error for missing translations.
# config.i18n.raise_on_missing_translations = true
config.i18n.fallbacks = [:en]
# Show emails using Letter Opener
config.action_mailer.delivery_method = :letter_opener
config.action_mailer.default_url_options = { host: "localhost:3000" }
# Annotate rendered view with file names.
# config.action_view.annotate_rendered_view_with_filenames = true
config.log_level = ENV.fetch("DEV_LOG_LEVEL", :debug)
# Uncomment if you wish to allow Action Cable access from any origin.
# config.action_cable.disable_request_forgery_protection = true
# Raise error when a before_action's only/except options reference missing actions
# config.action_controller.raise_on_missing_callback_actions = true
end

View File

@@ -1,69 +1,113 @@
Openfoodnetwork::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
require "active_support/core_ext/integer/time"
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# Code is not reloaded between requests.
config.enable_reloading = false
# Eager load code on boot. This eager loads most of Rails and
# your application in memory, allowing both threaded web servers
# and those relying on copy on write to perform better.
# Rake tasks automatically ignore this option for performance.
config.eager_load = true
# Code is not reloaded between requests
config.cache_classes = true
# Full error reports are disabled and caching is turned on
config.consider_all_requests_local = false
# Full error reports are disabled and caching is turned on.
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# Disable Rails's static asset server (Apache or nginx will already do this)
# Ensures that a master key has been made available in ENV["RAILS_MASTER_KEY"], config/master.key, or an environment
# key such as config/credentials/production.key. This key is used to decrypt credentials (and other encrypted files).
# config.require_master_key = true
# Disable serving static files from `public/`, relying on NGINX/Apache to do so instead.
config.public_file_server.enabled = false
# Compress CSS using a preprocessor.
# config.assets.css_compressor = :sass
# Do not fall back to assets pipeline if a precompiled asset is missed.
config.assets.compile = false
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.asset_host = "http://assets.example.com"
# Compress JavaScripts and CSS
config.assets.compress = true
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = false
# Generate digests for assets URLs
config.assets.digest = true
# Defaults to Rails.root.join("public/assets")
# config.assets.manifest = YOUR_PATH
# Specifies the header that your server uses for sending files.
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache
# config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX
# Specifies the header that your server uses for sending files
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
# Store uploaded files on the local file system (see config/storage.yml for options).
# We set it in application.rb.
# config.active_storage.service = :local
# Mount Action Cable outside main process or domain.
# config.action_cable.mount_path = nil
# config.action_cable.url = "wss://example.com/cable"
# config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ]
config.action_cable.url = "#{ENV['OFN_URL']}/cable"
config.action_cable.allowed_request_origins = [/http:\/\/#{ENV['OFN_URL']}\/*/, /https:\/\/#{ENV['OFN_URL']}\/*/]
# Assume all access to the app is happening through a SSL-terminating reverse proxy.
# Can be used together with config.force_ssl for Strict-Transport-Security and secure cookies.
# config.assume_ssl = true
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
config.force_ssl = true
# Use https in email links
config.action_mailer.default_url_options = { protocol: 'https' }
# Log to STDOUT by default
config.logger = ActiveSupport::Logger.new(STDOUT)
.tap { |logger| logger.formatter = ::Logger::Formatter.new }
.then { |logger| ActiveSupport::TaggedLogging.new(logger) }
# Set log level (default is :debug in Rails 4)
config.log_level = :info
# Configure logging:
config.log_formatter = Logger::Formatter.new.tap { |f| f.datetime_format = "%Y-%m-%d %H:%M:%S" }
# Prepend all log lines with the following tags.
config.log_tags = [:request_id]
# Use a different cache store in production
# "info" includes generic and useful information about system operation, but avoids logging too much
# information to avoid inadvertent exposure of personally identifiable information (PII). If you
# want to log everything, set the level to "debug".
config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info")
# Use a different cache store in production.
# config.cache_store = :mem_cache_store
config.cache_store = :redis_cache_store, {
url: ENV.fetch("OFN_REDIS_URL", "redis://localhost:6380/0"),
reconnect_attempts: 1
}
config.action_cable.url = "#{ENV['OFN_URL']}/cable"
config.action_cable.allowed_request_origins = [/http:\/\/#{ENV['OFN_URL']}\/*/, /https:\/\/#{ENV['OFN_URL']}\/*/]
# Use a real queuing backend for Active Job (and separate queues per environment).
# config.active_job.queue_adapter = :resque
# config.active_job.queue_name_prefix = "openfoodnetwork_production"
# Enable serving of images, stylesheets, and JavaScripts from an asset server
# config.action_controller.asset_host = "http://assets.example.com"
config.action_mailer.perform_caching = false
# Disable delivery errors, bad email addresses will be ignored
# Ignore bad email addresses and do not raise email delivery errors.
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
# config.action_mailer.raise_delivery_errors = false
# Enable threaded mode
# config.threadsafe!
# Use https in email links
config.action_mailer.default_url_options = { protocol: 'https' }
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation can not be found)
# the I18n.default_locale when a translation cannot be found).
config.i18n.fallbacks = [:en]
# Send deprecation notices to registered listeners
config.active_support.deprecation = :notify
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
# Enable DNS rebinding protection and other `Host` header attacks.
# config.hosts = [
# "example.com", # Allow requests from example.com
# /.*\.example\.com/ # Allow requests from subdomains like `www.example.com`
# ]
# Skip DNS rebinding protection for the default health check endpoint.
# config.host_authorization = { exclude: ->(request) { request.path == "/up" } }
end

View File

@@ -1,17 +1,38 @@
Openfoodnetwork::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
require "active_support/core_ext/integer/time"
# The test environment is used exclusively to run your application's
# test suite. You never need to work with it otherwise. Remember that
# your test database is "scratch space" for the test suite and is wiped
# and recreated between test runs. Don't rely on the data there!
# The test environment is used exclusively to run your application's
# test suite. You never need to work with it otherwise. Remember that
# your test database is "scratch space" for the test suite and is wiped
# and recreated between test runs. Don't rely on the data there!
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# While tests run files are not watched, reloading is not necessary.
config.enable_reloading = false
# StimulusReflex requires caching to be enabled.
config.cache_classes = false
# Eager loading loads your entire application. When running a single test locally,
# this is usually not necessary, and can slow down your test suite. However, it's
# recommended that you enable it in continuous integration systems to ensure eager
# loading is working properly before deploying your code.
# config.eager_load = ENV["CI"].present?
config.eager_load = false
# Configure static asset server for tests with Cache-Control for performance
config.time_zone = ENV.fetch("TIMEZONE", "UTC")
# Configure public file server for tests with Cache-Control for performance.
config.public_file_server.enabled = true
config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' }
config.public_file_server.headers = {
"Cache-Control" => "public, max-age=#{1.hour.to_i}"
}
# Show full error reports and disable caching.
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# config.cache_store = :null_store
# Separate cache stores when running in parallel
config.cache_store = :redis_cache_store, {
@@ -20,25 +41,61 @@ Openfoodnetwork::Application.configure do
reconnect_attempts: 1
}
# Show full error reports and disable caching
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Render exception templates for rescuable exceptions and raise for other exceptions.
config.action_dispatch.show_exceptions = :rescuable
# Raise exceptions instead of rendering exception templates
config.action_dispatch.show_exceptions = false
# Disable request forgery protection in test environment.
config.action_controller.allow_forgery_protection = false
# Disable request forgery protection in test environment
config.action_controller.allow_forgery_protection = false
# Store uploaded files on the local file system in a temporary directory.
# config.active_storage.service = :test
config.action_mailer.perform_caching = false
# Tell Action Mailer not to deliver emails to the real world.
# The :test delivery method accumulates sent emails in the
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
# Tests should fail when translations are missing.
config.i18n.raise_on_missing_translations = true
# Print deprecation notices to the stderr.
# config.active_support.deprecation = :stderr
config.time_zone = ENV.fetch("TIMEZONE", "UTC")
# Raise exceptions for disallowed deprecations.
config.active_support.disallowed_deprecation = :raise
# Tell Active Support which deprecation messages to disallow.
config.active_support.disallowed_deprecation_warnings = []
# Fail tests on deprecated code unless it's a known case to solve.
Rails.application.deprecators.behavior = ->(message, callstack, deprecator) do
allowed_warnings = [
# List strings here to allow matching deprecations.
#
# https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#new-activesupport-cache-serialization-format
"config.active_support.cache_format_version",
# `Rails.application.secrets` is deprecated in favor of `Rails.application.credentials` and will be removed in Rails 7.2
"Rails.application.secrets",
"Passing the class as positional argument",
# Spree::Order model aliases `bill_address`, but `bill_address` is not an attribute. Starting in Rails 7.2, alias_attribute with non-attribute targets will raise. Use `alias_method :billing_address, :bill_address` or define the method manually. (called from initialize at app/models/spree/order.rb:188)
"alias_attribute with non-attribute targets will raise",
# Spree::CreditCard model aliases `cc_type` and has a method called `cc_type=` defined. Starting in Rails 7.2 `brand=` will not be calling `cc_type=` anymore. You may want to additionally define `brand=` to preserve the current behavior.
"model aliases",
# Setting action_dispatch.show_exceptions to true is deprecated. Set to :all instead.
# spec/requests/errors_spec.rb
"action_dispatch.show_exceptions",
]
unless allowed_warnings.any? { |pattern| message.match(pattern) }
ActiveSupport::Deprecation::DEFAULT_BEHAVIORS[:raise].call(message, callstack, deprecator)
end
end
# Raises error for missing translations.
config.i18n.raise_on_missing_translations = true
# Tests assume English text on the site.
config.i18n.default_locale = "en"
@@ -46,23 +103,11 @@ Openfoodnetwork::Application.configure do
config.i18n.fallbacks = [:en]
I18n.locale = config.i18n.locale = config.i18n.default_locale
# Use SQL instead of Active Record's schema dumper when creating the test database.
# This is necessary if your schema can't be completely dumped by the schema dumper,
# like if you have constraints or database-specific column types
# config.active_record.schema_format = :sql
# Annotate rendered view with file names.
# config.action_view.annotate_rendered_view_with_filenames = true
# Print deprecation notices to the stderr
# config.active_support.deprecation = :stderr
# Fail tests on deprecated code unless it's a known case to solve.
ActiveSupport::Deprecation.behavior = ->(message, callstack, deprecation_horizon, gem_name) do
allowed_warnings = [
# List strings here to allow matching deprecations.
]
unless allowed_warnings.any? { |pattern| message.match(pattern) }
ActiveSupport::Deprecation::DEFAULT_BEHAVIORS[:raise].call(message, callstack, deprecation_horizon, gem_name)
end
end
# Raise error when a before_action's only/except options reference missing actions
# config.action_controller.raise_on_missing_callback_actions = true
config.active_job.queue_adapter = :test
end

View File

@@ -1 +1,24 @@
# Be sure to restart your server when you modify this file.
# Version of your assets, change this if you want to expire all your assets.
Rails.application.config.assets.version = "1.2"
# Add additional assets to the asset load path.
Rails.application.config.assets.paths << Rails.root.join('node_modules')
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in the app/assets
# folder are already added.
# Rails.application.config.assets.precompile += %w( admin.js admin.css )
# css and js files other than application.* are not precompiled by default
# Instead, they must be explicitly included below
# http://stackoverflow.com/questions/8012434/what-is-the-purpose-of-config-assets-precompile
Rails.application.config.assets.precompile += [
'admin/*.js', 'admin/**/*.js', 'admin_minimal.js',
'web/all.js',
'darkswarm/all.js',
'shared/*',
'mail.scss',
'*.jpg', '*.jpeg', '*.png', '*.gif' '*.svg',
]

View File

@@ -1,8 +1,8 @@
# Be sure to restart your server when you modify this file.
# Define an application-wide content security policy
# For further information see the following documentation
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
# Define an application-wide content security policy.
# See the Securing Rails Applications Guide for more information:
# https://guides.rubyonrails.org/security.html#content-security-policy-header
Rails.application.config.content_security_policy do |policy|
policy.default_src :self, :https
@@ -23,15 +23,11 @@ Rails.application.config.content_security_policy do |policy|
# Specify URI for violation reports
# policy.report_uri "/csp-violation-report-endpoint"
# Generate session nonces for permitted importmap, inline scripts, and inline styles.
# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
# config.content_security_policy_nonce_directives = %w(script-src style-src)
# Report violations without enforcing the policy.
# config.content_security_policy_report_only = true
end
# If you are using UJS then enable automatic nonce generation
# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
# Set the nonce only to specific directives
# Rails.application.config.content_security_policy_nonce_directives = %w(script-src)
# Report CSP violations to a specified URI
# For further information see the following documentation:
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only
# Rails.application.config.content_security_policy_report_only = true

View File

@@ -1,4 +1,12 @@
# frozen_string_literal: true
# Configure sensitive parameters which will be filtered from the log file.
Rails.application.config.filter_parameters += [:password, :vine_api_key, :vine_secret]
# Be sure to restart your server when you modify this file.
# Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file.
# Use this to limit dissemination of sensitive information.
# See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors.
Rails.application.config.filter_parameters += [
:passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn,
:number, :verification_value,
:vine_api_key, :vine_secret,
]

View File

@@ -1,13 +1,20 @@
# Be sure to restart your server when you modify this file.
# Add new inflection rules using the following format
# (all these examples are active by default):
# ActiveSupport::Inflector.inflections do |inflect|
# inflect.plural /^(ox)$/i, '\1en'
# inflect.singular /^(ox)en/i, '\1'
# inflect.irregular 'person', 'people'
# Add new inflection rules using the following format. Inflections
# are locale specific, and you may define rules for as many different
# locales as you wish. All of these examples are active by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.plural /^(ox)$/i, "\\1en"
# inflect.singular /^(ox)en/i, "\\1"
# inflect.irregular "person", "people"
# inflect.uncountable %w( fish sheep )
# end
# These inflection rules are supported but not enabled by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.acronym "RESTful"
# end
Rails.autoloaders.each do |autoloader|
autoloader.inflector.inflect(
"stripe_sca" => "StripeSCA"

View File

@@ -0,0 +1,143 @@
# Be sure to restart your server when you modify this file.
#
# This file eases your Rails 7.0 framework defaults upgrade.
#
# Uncomment each configuration one by one to switch to the new default.
# Once your application is ready to run with all new defaults, you can remove
# this file and set the `config.load_defaults` to `7.0`.
#
# Read the Guide for Upgrading Ruby on Rails for more info on each option.
# https://guides.rubyonrails.org/upgrading_ruby_on_rails.html
# `button_to` view helper will render `<button>` element, regardless of whether
# or not the content is passed as the first argument or as a block.
# Rails.application.config.action_view.button_to_generates_button_tag = true
# `stylesheet_link_tag` view helper will not render the media attribute by default.
# Rails.application.config.action_view.apply_stylesheet_media_default = false
# Change the digest class for the key generators to `OpenSSL::Digest::SHA256`.
# Changing this default means invalidate all encrypted messages generated by
# your application and, all the encrypted cookies. Only change this after you
# rotated all the messages using the key rotator.
#
# See upgrading guide for more information on how to build a rotator.
# https://guides.rubyonrails.org/v7.0/upgrading_ruby_on_rails.html
# Rails.application.config.active_support.key_generator_hash_digest_class = OpenSSL::Digest::SHA256
# Change the digest class for ActiveSupport::Digest.
# Changing this default means that for example Etags change and
# various cache keys leading to cache invalidation.
# Rails.application.config.active_support.hash_digest_class = OpenSSL::Digest::SHA256
# Don't override ActiveSupport::TimeWithZone.name and use the default Ruby
# implementation.
# Rails.application.config.active_support.remove_deprecated_time_with_zone_name = true
# Calls `Rails.application.executor.wrap` around test cases.
# This makes test cases behave closer to an actual request or job.
# Several features that are normally disabled in test, such as Active Record query cache
# and asynchronous queries will then be enabled.
# Rails.application.config.active_support.executor_around_test_case = true
# Set both the `:open_timeout` and `:read_timeout` values for `:smtp` delivery method.
# Rails.application.config.action_mailer.smtp_timeout = 5
# The ActiveStorage video previewer will now use scene change detection to generate
# better preview images (rather than the previous default of using the first frame
# of the video).
# Rails.application.config.active_storage.video_preview_arguments =
# "-vf 'select=eq(n\\,0)+eq(key\\,1)+gt(scene\\,0.015),loop=loop=-1:size=2,trim=start_frame=1' -frames:v 1 -f image2"
# Automatically infer `inverse_of` for associations with a scope.
# Rails.application.config.active_record.automatic_scope_inversing = true
# Raise when running tests if fixtures contained foreign key violations
# Rails.application.config.active_record.verify_foreign_keys_for_fixtures = true
# Disable partial inserts.
# This default means that all columns will be referenced in INSERT queries
# regardless of whether they have a default or not.
# Rails.application.config.active_record.partial_inserts = false
# Protect from open redirect attacks in `redirect_back_or_to` and `redirect_to`.
# Rails.application.config.action_controller.raise_on_open_redirects = true
# Change the variant processor for Active Storage.
# Changing this default means updating all places in your code that
# generate variants to use image processing macros and ruby-vips
# operations. See the upgrading guide for detail on the changes required.
# The `:mini_magick` option is not deprecated; it's fine to keep using it.
# Rails.application.config.active_storage.variant_processor = :vips
# Enable parameter wrapping for JSON.
# Previously this was set in an initializer. It's fine to keep using that initializer if you've customized it.
# To disable parameter wrapping entirely, set this config to `false`.
# Rails.application.config.action_controller.wrap_parameters_by_default = true
# Specifies whether generated namespaced UUIDs follow the RFC 4122 standard for namespace IDs provided as a
# `String` to `Digest::UUID.uuid_v3` or `Digest::UUID.uuid_v5` method calls.
#
# See https://guides.rubyonrails.org/configuring.html#config-active-support-use-rfc4122-namespaced-uuids for
# more information.
# Rails.application.config.active_support.use_rfc4122_namespaced_uuids = true
# Change the default headers to disable browsers' flawed legacy XSS protection.
# Rails.application.config.action_dispatch.default_headers = {
# "X-Frame-Options" => "SAMEORIGIN",
# "X-XSS-Protection" => "0",
# "X-Content-Type-Options" => "nosniff",
# "X-Download-Options" => "noopen",
# "X-Permitted-Cross-Domain-Policies" => "none",
# "Referrer-Policy" => "strict-origin-when-cross-origin"
# }
# ** Please read carefully, this must be configured in config/application.rb **
# Change the format of the cache entry.
# Changing this default means that all new cache entries added to the cache
# will have a different format that is not supported by Rails 6.1 applications.
# Only change this value after your application is fully deployed to Rails 7.0
# and you have no plans to rollback.
# When you're ready to change format, add this to `config/application.rb` (NOT this file):
# config.active_support.cache_format_version = 7.0
# Cookie serializer: 2 options
#
# If you're upgrading and haven't set `cookies_serializer` previously, your cookie serializer
# is `:marshal`. The default for new apps is `:json`.
#
# Rails.application.config.action_dispatch.cookies_serializer = :json
#
#
# To migrate an existing application to the `:json` serializer, use the `:hybrid` option.
#
# Rails transparently deserializes existing (Marshal-serialized) cookies on read and
# re-writes them in the JSON format.
#
# It is fine to use `:hybrid` long term; you should do that until you're confident *all* your cookies
# have been converted to JSON. To keep using `:hybrid` long term, move this config to its own
# initializer or to `config/application.rb`.
#
# Rails.application.config.action_dispatch.cookies_serializer = :hybrid
#
#
# If your cookies can't yet be serialized to JSON, keep using `:marshal` for backward-compatibility.
#
# If you have configured the serializer elsewhere, you can remove this section of the file.
#
# See https://guides.rubyonrails.org/action_controller_overview.html#cookies for more information.
# Change the return value of `ActionDispatch::Request#content_type` to the Content-Type header without modification.
# Rails.application.config.action_dispatch.return_only_request_media_type_on_content_type = false
# Active Storage `has_many_attached` relationships will default to replacing the current collection instead of appending to it.
# Thus, to support submitting an empty collection, the `file_field` helper will render an hidden field `include_hidden` by default when `multiple_file_field_include_hidden` is set to `true`.
# See https://guides.rubyonrails.org/configuring.html#config-active-storage-multiple-file-field-include-hidden for more information.
# Rails.application.config.active_storage.multiple_file_field_include_hidden = true
# ** Please read carefully, this must be configured in config/application.rb (NOT this file) **
# Disables the deprecated #to_s override in some Ruby core classes
# See https://guides.rubyonrails.org/configuring.html#config-active-support-disable-to-s-conversion for more information.
# config.active_support.disable_to_s_conversion = true

View File

@@ -0,0 +1,280 @@
# Be sure to restart your server when you modify this file.
#
# This file eases your Rails 7.1 framework defaults upgrade.
#
# Uncomment each configuration one by one to switch to the new default.
# Once your application is ready to run with all new defaults, you can remove
# this file and set the `config.load_defaults` to `7.1`.
#
# Read the Guide for Upgrading Ruby on Rails for more info on each option.
# https://guides.rubyonrails.org/upgrading_ruby_on_rails.html
###
# No longer add autoloaded paths into `$LOAD_PATH`. This means that you won't be able
# to manually require files that are managed by the autoloader, which you shouldn't do anyway.
#
# This will reduce the size of the load path, making `require` faster if you don't use bootsnap, or reduce the size
# of the bootsnap cache if you use it.
#
# To set this configuration, add the following line to `config/application.rb` (NOT this file):
# config.add_autoload_paths_to_load_path = false
###
# Remove the default X-Download-Options headers since it is used only by Internet Explorer.
# If you need to support Internet Explorer, add back `"X-Download-Options" => "noopen"`.
#++
# Rails.application.config.action_dispatch.default_headers = {
# "X-Frame-Options" => "SAMEORIGIN",
# "X-XSS-Protection" => "0",
# "X-Content-Type-Options" => "nosniff",
# "X-Permitted-Cross-Domain-Policies" => "none",
# "Referrer-Policy" => "strict-origin-when-cross-origin"
# }
###
# Do not treat an `ActionController::Parameters` instance
# as equal to an equivalent `Hash` by default.
#++
# Rails.application.config.action_controller.allow_deprecated_parameters_hash_equality = false
###
# Active Record Encryption now uses SHA-256 as its hash digest algorithm.
#
# There are 3 scenarios to consider.
#
# 1. If you have data encrypted with previous Rails versions, and you have
# +config.active_support.key_generator_hash_digest_class+ configured as SHA1 (the default
# before Rails 7.0), you need to configure SHA-1 for Active Record Encryption too:
#++
# Rails.application.config.active_record.encryption.hash_digest_class = OpenSSL::Digest::SHA1
#
# 2. If you have +config.active_support.key_generator_hash_digest_class+ configured as SHA256 (the new default
# in 7.0), then you need to configure SHA-256 for Active Record Encryption:
#++
# Rails.application.config.active_record.encryption.hash_digest_class = OpenSSL::Digest::SHA256
#
# 3. If you don't currently have data encrypted with Active Record encryption, you can disable this setting to
# configure the default behavior starting 7.1+:
#++
# Rails.application.config.active_record.encryption.support_sha1_for_non_deterministic_encryption = false
###
# No longer run after_commit callbacks on the first of multiple Active Record
# instances to save changes to the same database row within a transaction.
# Instead, run these callbacks on the instance most likely to have internal
# state which matches what was committed to the database, typically the last
# instance to save.
#++
# Rails.application.config.active_record.run_commit_callbacks_on_first_saved_instances_in_transaction = false
###
# Configures SQLite with a strict strings mode, which disables double-quoted string literals.
#
# SQLite has some quirks around double-quoted string literals.
# It first tries to consider double-quoted strings as identifier names, but if they don't exist
# it then considers them as string literals. Because of this, typos can silently go unnoticed.
# For example, it is possible to create an index for a non existing column.
# See https://www.sqlite.org/quirks.html#double_quoted_string_literals_are_accepted for more details.
#++
# Rails.application.config.active_record.sqlite3_adapter_strict_strings_by_default = true
###
# Disable deprecated singular associations names.
#++
# Rails.application.config.active_record.allow_deprecated_singular_associations_name = false
###
# Enable the Active Job `BigDecimal` argument serializer, which guarantees
# roundtripping. Without this serializer, some queue adapters may serialize
# `BigDecimal` arguments as simple (non-roundtrippable) strings.
#
# When deploying an application with multiple replicas, old (pre-Rails 7.1)
# replicas will not be able to deserialize `BigDecimal` arguments from this
# serializer. Therefore, this setting should only be enabled after all replicas
# have been successfully upgraded to Rails 7.1.
#++
# Rails.application.config.active_job.use_big_decimal_serializer = true
###
# Specify if an `ArgumentError` should be raised if `Rails.cache` `fetch` or
# `write` are given an invalid `expires_at` or `expires_in` time.
# Options are `true`, and `false`. If `false`, the exception will be reported
# as `handled` and logged instead.
#++
# Rails.application.config.active_support.raise_on_invalid_cache_expiration_time = true
###
# Specify whether Query Logs will format tags using the SQLCommenter format
# (https://open-telemetry.github.io/opentelemetry-sqlcommenter/), or using the legacy format.
# Options are `:legacy` and `:sqlcommenter`.
#++
# Rails.application.config.active_record.query_log_tags_format = :sqlcommenter
###
# Specify the default serializer used by `MessageEncryptor` and `MessageVerifier`
# instances.
#
# The legacy default is `:marshal`, which is a potential vector for
# deserialization attacks in cases where a message signing secret has been
# leaked.
#
# In Rails 7.1, the new default is `:json_allow_marshal` which serializes and
# deserializes with `ActiveSupport::JSON`, but can fall back to deserializing
# with `Marshal` so that legacy messages can still be read.
#
# In Rails 7.2, the default will become `:json` which serializes and
# deserializes with `ActiveSupport::JSON` only.
#
# Alternatively, you can choose `:message_pack` or `:message_pack_allow_marshal`,
# which serialize with `ActiveSupport::MessagePack`. `ActiveSupport::MessagePack`
# can roundtrip some Ruby types that are not supported by JSON, and may provide
# improved performance, but it requires the `msgpack` gem.
#
# For more information, see
# https://guides.rubyonrails.org/v7.1/configuring.html#config-active-support-message-serializer
#
# If you are performing a rolling deploy of a Rails 7.1 upgrade, wherein servers
# that have not yet been upgraded must be able to read messages from upgraded
# servers, first deploy without changing the serializer, then set the serializer
# in a subsequent deploy.
#++
# Rails.application.config.active_support.message_serializer = :json_allow_marshal
###
# Enable a performance optimization that serializes message data and metadata
# together. This changes the message format, so messages serialized this way
# cannot be read by older versions of Rails. However, messages that use the old
# format can still be read, regardless of whether this optimization is enabled.
#
# To perform a rolling deploy of a Rails 7.1 upgrade, wherein servers that have
# not yet been upgraded must be able to read messages from upgraded servers,
# leave this optimization off on the first deploy, then enable it on a
# subsequent deploy.
#++
# Rails.application.config.active_support.use_message_serializer_for_metadata = true
###
# Set the maximum size for Rails log files.
#
# `config.load_defaults 7.1` does not set this value for environments other than
# development and test.
#++
# if Rails.env.local?
# Rails.application.config.log_file_size = 100 * 1024 * 1024
# end
###
# Enable raising on assignment to attr_readonly attributes. The previous
# behavior would allow assignment but silently not persist changes to the
# database.
#++
# Rails.application.config.active_record.raise_on_assign_to_attr_readonly = true
###
# Enable validating only parent-related columns for presence when the parent is mandatory.
# The previous behavior was to validate the presence of the parent record, which performed an extra query
# to get the parent every time the child record was updated, even when parent has not changed.
#++
# Rails.application.config.active_record.belongs_to_required_validates_foreign_key = false
###
# Enable precompilation of `config.filter_parameters`. Precompilation can
# improve filtering performance, depending on the quantity and types of filters.
#++
# Rails.application.config.precompile_filter_parameters = true
###
# Enable before_committed! callbacks on all enrolled records in a transaction.
# The previous behavior was to only run the callbacks on the first copy of a record
# if there were multiple copies of the same record enrolled in the transaction.
#++
# Rails.application.config.active_record.before_committed_on_all_records = true
###
# Disable automatic column serialization into YAML.
# To keep the historic behavior, you can set it to `YAML`, however it is
# recommended to explicitly define the serialization method for each column
# rather than to rely on a global default.
#++
# Rails.application.config.active_record.default_column_serializer = nil
###
# Enable a performance optimization that serializes Active Record models
# in a faster and more compact way.
#
# To perform a rolling deploy of a Rails 7.1 upgrade, wherein servers that have
# not yet been upgraded must be able to read caches from upgraded servers,
# leave this optimization off on the first deploy, then enable it on a
# subsequent deploy.
#++
# Rails.application.config.active_record.marshalling_format_version = 7.1
###
# Run `after_commit` and `after_*_commit` callbacks in the order they are defined in a model.
# This matches the behaviour of all other callbacks.
# In previous versions of Rails, they ran in the inverse order.
#++
# Rails.application.config.active_record.run_after_transaction_callbacks_in_order_defined = true
###
# Whether a `transaction` block is committed or rolled back when exited via `return`, `break` or `throw`.
#++
# Rails.application.config.active_record.commit_transaction_on_non_local_return = true
###
# Controls when to generate a value for <tt>has_secure_token</tt> declarations.
#++
# Rails.application.config.active_record.generate_secure_token_on = :initialize
###
# ** Please read carefully, this must be configured in config/application.rb **
#
# Change the format of the cache entry.
#
# Changing this default means that all new cache entries added to the cache
# will have a different format that is not supported by Rails 7.0
# applications.
#
# Only change this value after your application is fully deployed to Rails 7.1
# and you have no plans to rollback.
# When you're ready to change format, add this to `config/application.rb` (NOT
# this file):
# config.active_support.cache_format_version = 7.1
###
# Configure Action View to use HTML5 standards-compliant sanitizers when they are supported on your
# platform.
#
# `Rails::HTML::Sanitizer.best_supported_vendor` will cause Action View to use HTML5-compliant
# sanitizers if they are supported, else fall back to HTML4 sanitizers.
#
# In previous versions of Rails, Action View always used `Rails::HTML4::Sanitizer` as its vendor.
#++
# Rails.application.config.action_view.sanitizer_vendor = Rails::HTML::Sanitizer.best_supported_vendor
###
# Configure Action Text to use an HTML5 standards-compliant sanitizer when it is supported on your
# platform.
#
# `Rails::HTML::Sanitizer.best_supported_vendor` will cause Action Text to use HTML5-compliant
# sanitizers if they are supported, else fall back to HTML4 sanitizers.
#
# In previous versions of Rails, Action Text always used `Rails::HTML4::Sanitizer` as its vendor.
#++
# Rails.application.config.action_text.sanitizer_vendor = Rails::HTML::Sanitizer.best_supported_vendor
###
# Configure the log level used by the DebugExceptions middleware when logging
# uncaught exceptions during requests.
#++
# Rails.application.config.action_dispatch.debug_exception_log_level = :error
###
# Configure the test helpers in Action View, Action Dispatch, and rails-dom-testing to use HTML5
# parsers.
#
# Nokogiri::HTML5 isn't supported on JRuby, so JRuby applications must set this to :html4.
#
# In previous versions of Rails, these test helpers always used an HTML4 parser.
#++
# Rails.application.config.dom_testing_default_html_version = :html5

View File

@@ -0,0 +1,13 @@
# Be sure to restart your server when you modify this file.
# Define an application-wide HTTP permissions policy. For further
# information see: https://developers.google.com/web/updates/2018/06/feature-policy
# Rails.application.config.permissions_policy do |policy|
# policy.camera :none
# policy.gyroscope :none
# policy.microphone :none
# policy.usb :none
# policy.fullscreen :self
# policy.payment :self, "https://secure.example.com"
# end

View File

@@ -1446,6 +1446,8 @@ cy:
visible: Gweladwy?
owner: Perchennog
producer: Cynhyrchydd
sells_options:
none: dim
change_type_form:
producer_profile: Proffil Cynhyrchydd
connect_ofn: Cysylltu trwy'r Open Food Network

View File

@@ -1518,6 +1518,11 @@ en:
visible: Visible?
owner: Owner
producer: Producer
sells_options:
unspecified: unspecified
none: none
own: own
any: any
change_type_form:
producer_profile: Producer Profile
connect_ofn: Connect through OFN

View File

@@ -1447,6 +1447,8 @@ en_CA:
visible: Visible?
owner: Owner
producer: Producer
sells_options:
none: none
change_type_form:
producer_profile: Producer Profile
connect_ofn: Connect through OFN
@@ -3315,6 +3317,7 @@ en_CA:
product_importer_products_save_error: did not save any products successfully
product_import_file_not_found_notice: 'File not found or could not be opened'
product_import_no_data_in_spreadsheet_notice: 'No data found in spreadsheet'
product_import_inventory_disable: Importing into inventories is not available
order_choosing_hub_notice: Your hub has been selected.
order_cycle_selecting_notice: Your order cycle has been selected.
adjustments_tax_rate_error: "^Please check that the tax rate for this adjustment is correct."
@@ -3617,7 +3620,7 @@ en_CA:
removed_terms_and_conditions_successfully: "Terms and Conditions file removed successfully"
insufficient_stock: "Insufficient stock available, only %{on_hand} remaining"
out_of_stock:
reduced_stock_available: Reduced stock available
reduced_stock_available: 'Reduced stock '
out_of_stock_text: >
While you've been shopping, the stock levels for one or more of the products
in your cart have reduced. Here's what's changed:

View File

@@ -1447,6 +1447,8 @@ en_FR:
visible: Visible?
owner: Owner
producer: Producer
sells_options:
none: none
change_type_form:
producer_profile: Producer Profile
connect_ofn: Connect through OFN
@@ -3315,6 +3317,7 @@ en_FR:
product_importer_products_save_error: did not save any products successfully
product_import_file_not_found_notice: 'File not found or could not be opened'
product_import_no_data_in_spreadsheet_notice: 'No data found in spreadsheet'
product_import_inventory_disable: Importing into inventories is not available
order_choosing_hub_notice: Your hub has been selected.
order_cycle_selecting_notice: Your order cycle has been selected.
adjustments_tax_rate_error: "^Please check that the tax rate for this adjustment is correct."

View File

@@ -1447,6 +1447,8 @@ en_GB:
visible: Visible?
owner: Owner
producer: Producer
sells_options:
none: none
change_type_form:
producer_profile: Producer Profile
connect_ofn: Connect through OFN

View File

@@ -1445,6 +1445,8 @@ fi:
visible: Näkyvissä?
owner: Omistaja
producer: Tuottaja
sells_options:
none: ei yhtään
change_type_form:
producer_profile: Tuottajan profiili
connect_ofn: Yhdistä OFN:n kautta

View File

@@ -1449,6 +1449,8 @@ fr:
visible: Visible?
owner: Gestionnaire principal
producer: Producteur
sells_options:
none: aucun
change_type_form:
producer_profile: Profil simple
connect_ofn: Pour apparaître sur la carte et la liste des producteurs
@@ -3321,6 +3323,7 @@ fr:
product_importer_products_save_error: n'a pu sauvegarder aucun produit :-(
product_import_file_not_found_notice: 'Fichier non trouvé ou impossible à ouvrir'
product_import_no_data_in_spreadsheet_notice: 'Aucune donnée trouvée dans le tableau'
product_import_inventory_disable: L'importation vers les catalogues boutique n'est pas disponible
order_choosing_hub_notice: Votre boutique a été sélectionnée.
order_cycle_selecting_notice: Votre cycle de vente a été sélectionné.
adjustments_tax_rate_error: "^Veuillez vérifier la TVA applicable pour cet ajustement."

View File

@@ -1451,6 +1451,8 @@ fr_CA:
visible: Visible?
owner: Gérant
producer: Producteur
sells_options:
none: aucun
change_type_form:
producer_profile: Profil producteur
connect_ofn: Gagnez en visibilité via OFN
@@ -3322,6 +3324,7 @@ fr_CA:
product_importer_products_save_error: n'a pu sauvegarder aucun produit :-(
product_import_file_not_found_notice: 'Fichier non trouvé ou impossible à ouvrir'
product_import_no_data_in_spreadsheet_notice: 'Aucune donnée trouvée dans le tableau'
product_import_inventory_disable: L'importation vers les catalogues boutique n'est pas disponible
order_choosing_hub_notice: Votre hub a été sélectionné.
order_cycle_selecting_notice: Votre cycle de vente a été sélectionné.
adjustments_tax_rate_error: "^Veuillez vérifier le type de taxe applicable pour cet ajustement."

View File

@@ -530,7 +530,7 @@ hu:
save: "Mentés"
edit: "Szerkesztés"
update: "Frissítés"
delete: "Töröl"
delete: "Törlés"
add: "Hozzáadás"
cut: "Kivágás"
paste: "Beillesztés"
@@ -580,7 +580,7 @@ hu:
actions:
edit: Szerkesztés
clone: Klón
delete: Töröl
delete: Törlés
remove: Eltávolítás
preview: Előnézet
image:
@@ -907,7 +907,7 @@ hu:
success: Sikeresen klónozta a terméket
error: A terméket nem sikerült klónozni
product_import:
title: Termék importálása
title: Termék importálás
file_not_found: A fájl nem található, vagy nem nyitható meg
no_data: Nem található adat a táblázatban
confirm_reset: "Ezzel nullára állítod a készletszintet a vállalkozás összes olyan termékénél, \namely nem szerepel a feltöltött fájlban"
@@ -922,7 +922,7 @@ hu:
not_updatable: nem frissíthető a meglévő termékeken termékimporttal
values_must_be_same: azonos név alatt azonos terméknek kell szerepelnie
blank: nem lehet üres
products_no_permission: nincs engedélye a vállalkozás termékeinek kezelésére
products_no_permission: nincs engedélyed a vállalkozás termékeinek kezelésére
inventory_no_permission: nincs engedélye készlet létrehozására ehhez a termelőhöz
none_saved: egyetlen terméket sem mentett sikeresen
line_number: "%{number}. sor:"
@@ -970,6 +970,7 @@ hu:
no_name: Névtelen
blank_enterprise: egyes termékekhez nincs definiálva a vállalkozás
reset_absent?: Hiányzó termékek visszaállítása
reset_absent_tip: Állítsa nullára a készletet az összes olyan terméknél, amely nem szerepel a fájlban
overwrite_all: Az összes felülírása
overwrite_empty: Ha üres, írja felül
default_stock: Állítsd be a készletet
@@ -977,15 +978,15 @@ hu:
default_shipping_cat: Szállítási kategória beállítása
default_available_date: Állítsd be az elérhetőségi dátumot
validation_overview: Az importálás ellenőrzésének áttekintése
entries_found: Bejegyzések találhatók az importált fájlban
entries_found: bejegyzés található az importált fájlban
entries_with_errors: Az elemek hibákat tartalmaznak, és nem importálhatók
products_to_create: Termékek jönnek létre
products_to_create: termék jön létre
products_to_update: A termékek frissítésre kerülnek
inventory_to_create: A készletelemek létrehozásra kerülnek
inventory_to_update: A készletelemek frissülnek
products_to_reset: A meglévő termékek készlete nullára áll vissza
inventory_to_reset: A meglévő készletelemek készlete nullára áll vissza
line: Vonal
line: Sor
item_line: Tételsor
import_review:
not_updatable_tip: "A következő mezők nem frissíthetők tömeges importálással meglévő termékek esetén:"
@@ -993,14 +994,14 @@ hu:
entries_table:
not_updatable: Ez a mező nem frissíthető tömeges importálással meglévő termékeken
save_results:
final_results: Végső eredmények importálása
products_created: Létrehozott termékek
final_results: Az importálás eredménye
products_created: létrehozott termék
products_updated: Termékek frissítve
inventory_created: Készletelemek létrehozva
inventory_updated: A készletelemek frissítve
products_reset: A termékek készletszintjét nullára állítottuk vissza
products_reset: termék készletét nullára állítottuk
inventory_reset: A készletelemek készletszintjét nullára állították vissza
all_saved: "Minden elem sikeresen mentve"
all_saved: "Minden termék mentése sikeres."
some_saved: "elemek sikeresen mentve"
save_errors: Mentse el a hibákat
import_again: Másik fájl feltöltése
@@ -1011,7 +1012,7 @@ hu:
producer: Termelő
sku: SKU
name: Név
display_name: Megjelenítendő név
display_name: Alternatív név
category: Kategória
description: Leírás
units: Egységek
@@ -1382,6 +1383,8 @@ hu:
visible: Látható?
owner: Tulajdonos
producer: Termelő
sells_options:
none: n.a.
change_type_form:
producer_profile: Termelői Profil
connect_ofn: Csatlakozás OFN-en keresztül
@@ -1518,7 +1521,7 @@ hu:
add_distributor: 'Elosztó hozzáadása'
advanced_settings:
automatic_notifications: Automatikus értesítések
automatic_notifications_tip: Automatikusan értesíti a termelőket rendeléseikről e-mailben, amikor a rendelési ciklusok lezárulnak
automatic_notifications_tip: Automatikusan értesíti a termelőket rendeléseikről e-mailben, amikor a rendelés ciklus lezárul
title: További beállítások
choose_product_tip: bejövő és kimenő termékeket csak %{inventory} készletére korlátozhatja.
preferred_product_selection_from_coordinator_inventory_only_here: Csak a koordinátor leltár
@@ -2397,11 +2400,11 @@ hu:
set_a_password: "Ezután a rendszer kéri, hogy állítson be egy jelszót, mielőtt felügyelheti a vállalkozást."
mistakenly_sent: "Nem tudod, miért kaptad ezt az e-mailt? További információért fordulj %{owner_email}-hoz."
producer_mail_greeting: "Kedves"
producer_mail_text_before: "Alább megtalálja a rendelési ciklusra vonatkozó frissítést:"
producer_mail_order_text: "Íme a termékei megrendelésének összefoglalása:"
producer_mail_text_before: "Küldjük az alábbi rendelési ciklusra vonatkozó összesítést:"
producer_mail_order_text: "Megrendelt termékek:"
producer_mail_delivery_instructions: "Raktári átvételi/szállítási instrukciók:"
producer_mail_signoff: "Köszönet és jókívánságok"
producer_mail_order_customer_text: "Itt található a rendelések összegzése ügyfelek szerint csoportosítva"
producer_mail_signoff: "Üdvözlettel,"
producer_mail_order_customer_text: "A rendelések vásárlók szerint csoportosítva:"
shopping_oc_closed: A rendelések lezárva
shopping_oc_closed_description: "Kérjük, várd meg, amíg a következő ciklus megnyílik."
shopping_oc_last_closed: "Az utolsó ciklus ennyi ideje zárult: %{distance_of_time}"
@@ -2865,7 +2868,7 @@ hu:
admin_enterprise_groups_web_website_placeholder: "például www.truffles.com"
admin_order_cycles: "Admin Rendelési Ciklusok"
open: "Nyit"
close: "Zár"
close: "Bezárás"
create: "Létrehozás"
search: "Keresés"
supplier: "Beszállító"
@@ -2902,7 +2905,7 @@ hu:
edit_order_cycle: "Rendelési Ciklus Szerkesztése"
roles: "Szerepek"
update: "Frissítés"
delete: Töröl
delete: Törlés
add_producer_property: "Termelői tulajdonság hozzáadása"
in_progress: "Folyamatban"
started_at: "Kezdődött:"
@@ -3472,7 +3475,7 @@ hu:
compiling_invoices: "Vevői lapok összeállítása"
bulk_invoice_created: "Vevői lapok létrehozva"
bulk_invoice_failed: "Nem sikerült létrehozni a tömeges számlát"
please_wait: "A modul bezárása előtt várja meg, amíg a PDF elkészül."
please_wait: "A modul bezárása előtt várd meg, amíg a PDF elkészül."
order_state:
address: "cím"
adjustments: "kiigazításokat"
@@ -3888,7 +3891,7 @@ hu:
total: "Összesen"
edit: "Szerkesztés"
split: "Hasított"
delete: "Töröl"
delete: "Törlés"
cannot_set_shipping_method_without_address: "A áruátvételi módot nem lehet beállítani, amíg meg nem adják az ügyfél adatait."
no_tracking_present: "Nincsenek megadva nyomkövetési adatok."
tracking: "Követés"
@@ -4445,7 +4448,7 @@ hu:
sku: "SKU"
unit_price: "Egységár"
display_as: "Megjelenítés mint"
display_name: "Megjelenítendő név"
display_name: "Alternatív név"
display_as_placeholder: 'például 2 kg'
display_name_placeholder: 'például paradicsom'
unit_scale: "Mértékegység skála"

View File

@@ -73,17 +73,13 @@ Openfoodnetwork::Application.routes.draw do
post :import, on: :collection
end
constraints FeatureToggleConstraint.new(:admin_style_v3) do
# This might be easier to arrange once we rename the controller to plain old "products"
post '/products/bulk_update', to: 'products_v3#bulk_update'
get '/products', to: 'products_v3#index'
# we already have DELETE admin/products/:id here
delete 'products_v3/:id', to: 'products_v3#destroy', as: 'product_destroy'
delete 'products_v3/destroy_variant/:id', to: 'products_v3#destroy_variant', as: 'destroy_variant'
post 'clone/:id', to: 'products_v3#clone', as: 'clone_product'
resources :product_preview, only: [:show]
end
# This might be easier to arrange once we rename the controller to plain old "products"
post '/products/bulk_update', to: 'products_v3#bulk_update', as: 'products_bulk_update'
get '/products', to: 'products_v3#index', as: 'products'
delete 'products_v3/:id', to: 'products_v3#destroy', as: 'product_destroy'
delete 'products_v3/destroy_variant/:id', to: 'products_v3#destroy_variant', as: 'destroy_variant'
post 'clone/:id', to: 'products_v3#clone', as: 'clone_product'
resources :product_preview, only: [:show]
resources :variant_overrides do
post :bulk_update, on: :collection

View File

@@ -50,16 +50,8 @@ Spree::Core::Engine.routes.draw do
resources :users
constraints FeatureToggleConstraint.new(:admin_style_v3, negate: true) do
# Show old bulk products screen
resources :products, :index do
post :bulk_update, :on => :collection, :as => :bulk_update
end
end
resources :products, except: :index do
resources :products, except: [:index, :destroy] do
member do
get :clone
get :group_buy_options
get :seo
end
@@ -83,11 +75,6 @@ Spree::Core::Engine.routes.draw do
end
end
if Rails.env.development?
# duplicate old path for reference when admin_style_v3 enabled
resources :products_old, to: 'products#index', only: :index
end
get '/variants/search', :to => "variants#search", :as => :search_variants
resources :properties

View File

@@ -1,5 +0,0 @@
class ActivateAdminStyleV3ForNewUsers < ActiveRecord::Migration[7.0]
def up
Flipper.enable_group(:admin_style_v3, :new_2024_07_03)
end
end

View File

@@ -1,5 +0,0 @@
class EnableFeatureAdminStyleV3ForAdmins < ActiveRecord::Migration[7.0]
def up
Flipper.enable_group(:admin_style_v3, :admins)
end
end

View File

@@ -1,7 +0,0 @@
class EnableAdminStyleV3ByDefault < ActiveRecord::Migration[7.0]
def up
if Rails.env.development?
Flipper.enable(:admin_style_v3)
end
end
end

View File

@@ -1,5 +0,0 @@
class ActivateAdminStyleV3For25PCentUsers < ActiveRecord::Migration[7.0]
def up
Flipper.enable_percentage_of_actors(:admin_style_v3, 25)
end
end

View File

@@ -1,5 +0,0 @@
class ActivateAdminStyleV3For50PcUsers < ActiveRecord::Migration[7.0]
def up
Flipper.enable_percentage_of_actors(:admin_style_v3, 50)
end
end

View File

@@ -1,9 +0,0 @@
class ActivateAdminStyleV3For75PcUsers < ActiveRecord::Migration[7.0]
def up
Flipper.enable_percentage_of_actors(:admin_style_v3, 75)
end
def down
Flipper.enable_percentage_of_actors(:admin_style_v3, 50)
end
end

View File

@@ -1,5 +0,0 @@
class FullyEnableAdminStyleV3Flag < ActiveRecord::Migration[7.0]
def up
Flipper.enable(:admin_style_v3)
end
end

View File

@@ -0,0 +1,16 @@
# frozen_string_literal: true
class CreateDfcPermissions < ActiveRecord::Migration[7.0]
def change
create_table :dfc_permissions do |t|
t.references :user, null: false, foreign_key: { to_table: :spree_users }
t.references :enterprise, null: false, foreign_key: true
t.string :grantee, null: false
t.string :scope, null: false
t.timestamps
end
add_index :dfc_permissions, :grantee
add_index :dfc_permissions, :scope
end
end

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