mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-22 20:16:50 +00:00
Compare commits
325 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b78f8b855 | ||
|
|
1e2b28c559 | ||
|
|
4577bde692 | ||
|
|
af6be02ba4 | ||
|
|
0dabca583f | ||
|
|
d7603755bf | ||
|
|
f9d255a266 | ||
|
|
bcf4507795 | ||
|
|
9967ba2d06 | ||
|
|
f90f71cf68 | ||
|
|
fe8a0a908e | ||
|
|
bf6176c883 | ||
|
|
ffdfb7d450 | ||
|
|
3aa4c2a25f | ||
|
|
3331aaa382 | ||
|
|
b302dcfbec | ||
|
|
7dfc4d21ca | ||
|
|
f332a6934b | ||
|
|
baad0135f9 | ||
|
|
1973e36634 | ||
|
|
2e62531232 | ||
|
|
d811103a71 | ||
|
|
f3efed7aeb | ||
|
|
01278c3ee6 | ||
|
|
da7f46de1f | ||
|
|
20107986a6 | ||
|
|
dbd0100044 | ||
|
|
7f108353e3 | ||
|
|
e1775eaad8 | ||
|
|
ad9ebc2f92 | ||
|
|
fa4351599f | ||
|
|
e5ba0843d8 | ||
|
|
71fe5bc107 | ||
|
|
3c3b591655 | ||
|
|
39c7fbef46 | ||
|
|
cff52beb06 | ||
|
|
c4fec2ee76 | ||
|
|
952fc15a64 | ||
|
|
2cbd5b5255 | ||
|
|
9f77c5912f | ||
|
|
1e4c0cb2cc | ||
|
|
ded139458d | ||
|
|
e5f9c39352 | ||
|
|
f0554d8ae2 | ||
|
|
e37caf7a96 | ||
|
|
03653bee60 | ||
|
|
43cf6e4147 | ||
|
|
7f01658f47 | ||
|
|
7701561755 | ||
|
|
0bdee785bb | ||
|
|
1029b61bb0 | ||
|
|
065e7a420b | ||
|
|
fe4b6accb0 | ||
|
|
1049ec277c | ||
|
|
b3314d7441 | ||
|
|
77121dfacf | ||
|
|
04323388ad | ||
|
|
700be792e5 | ||
|
|
9f2ece379a | ||
|
|
2662371507 | ||
|
|
172647f1cd | ||
|
|
24fc3e9e86 | ||
|
|
b064173b7a | ||
|
|
f95581cd1f | ||
|
|
b113fe08e1 | ||
|
|
93d73f4763 | ||
|
|
154d17969c | ||
|
|
e32dcd53b5 | ||
|
|
44c4a66970 | ||
|
|
d05834b896 | ||
|
|
854e136d09 | ||
|
|
7f3fc4ff91 | ||
|
|
62ae62db5a | ||
|
|
a6fc49abce | ||
|
|
528c5a3593 | ||
|
|
81165cd82b | ||
|
|
faf50a1922 | ||
|
|
5f237adda2 | ||
|
|
2e09a96c4b | ||
|
|
6ae47c208a | ||
|
|
82139a9ac0 | ||
|
|
6d9946c3c6 | ||
|
|
f58b6bcada | ||
|
|
dc13ef4162 | ||
|
|
dcb48272f5 | ||
|
|
08bc374576 | ||
|
|
afbf0a5d0e | ||
|
|
7e034a3037 | ||
|
|
2db2fb2f11 | ||
|
|
74d2a94181 | ||
|
|
7a5b273e71 | ||
|
|
0b6e7593db | ||
|
|
6d0d91c56a | ||
|
|
a509d49ec6 | ||
|
|
dddc945c42 | ||
|
|
12c0363b7e | ||
|
|
bb0903cd4a | ||
|
|
e93cb485a1 | ||
|
|
fbce264dd7 | ||
|
|
3c1313bfa0 | ||
|
|
4ca420bd84 | ||
|
|
134ea28249 | ||
|
|
78cfc0db65 | ||
|
|
816e06d37c | ||
|
|
2e80b7d92f | ||
|
|
753173e2be | ||
|
|
c9954f0823 | ||
|
|
80f5fa30c4 | ||
|
|
9194d0ba2b | ||
|
|
e00c993a98 | ||
|
|
800333f65b | ||
|
|
64df7cc9bc | ||
|
|
b23fec268e | ||
|
|
7b7a7d3418 | ||
|
|
6fa99b187d | ||
|
|
a009dacd41 | ||
|
|
472ba98ec2 | ||
|
|
91cd3356b0 | ||
|
|
67ef142546 | ||
|
|
0aa4993a4d | ||
|
|
98176bd5de | ||
|
|
dde0e23a79 | ||
|
|
d1021210e6 | ||
|
|
bfa472a293 | ||
|
|
9d14c1026c | ||
|
|
c653743a56 | ||
|
|
28af42371b | ||
|
|
acfe180e1d | ||
|
|
7d20eb4fea | ||
|
|
a1ee1eac4c | ||
|
|
84b351e076 | ||
|
|
9f7faac842 | ||
|
|
02c1b309f3 | ||
|
|
58028df3b7 | ||
|
|
638c139bca | ||
|
|
5adfdf11fb | ||
|
|
152a7b7fe9 | ||
|
|
5c998bfc77 | ||
|
|
97ca8702d4 | ||
|
|
e194ebf0f3 | ||
|
|
f6fc8a6993 | ||
|
|
cbf6b4462e | ||
|
|
c03580180a | ||
|
|
77b72134d8 | ||
|
|
c638e2e65e | ||
|
|
25ac714cc6 | ||
|
|
475e6c33f1 | ||
|
|
ae70a1372b | ||
|
|
6eb6bf634f | ||
|
|
a82209af85 | ||
|
|
ecf0d53f0a | ||
|
|
fc047e3f7c | ||
|
|
d9e3076a3b | ||
|
|
271e895486 | ||
|
|
3e02a03312 | ||
|
|
ec31ff418d | ||
|
|
22f3577b0d | ||
|
|
9c9773f493 | ||
|
|
33cea470ad | ||
|
|
17ac3507a6 | ||
|
|
763655f0e5 | ||
|
|
7cf0a95688 | ||
|
|
c641fae2b9 | ||
|
|
526df1cb9c | ||
|
|
f4e9daec80 | ||
|
|
3e2cd839cc | ||
|
|
b9a790ba20 | ||
|
|
aaad1bc0b3 | ||
|
|
d7f4a5c874 | ||
|
|
f8ca8ae942 | ||
|
|
2805ea4926 | ||
|
|
36ac5dc44e | ||
|
|
49a976810b | ||
|
|
f6d605a3aa | ||
|
|
6901323827 | ||
|
|
186fe0503f | ||
|
|
e990e5ffd5 | ||
|
|
3d7207d8c5 | ||
|
|
4b31352e4f | ||
|
|
278a8b1ec2 | ||
|
|
b96a0875f3 | ||
|
|
4e62e20fa8 | ||
|
|
2729fb14d6 | ||
|
|
5dab6f67f2 | ||
|
|
3aa48fcd18 | ||
|
|
e5fd5a0d4c | ||
|
|
ad5a22a69b | ||
|
|
43b3114237 | ||
|
|
a83109cb05 | ||
|
|
72327a352e | ||
|
|
35ef895cff | ||
|
|
52e4293e90 | ||
|
|
460d109bd2 | ||
|
|
7d0f17fe1a | ||
|
|
cff6fcf52e | ||
|
|
4083aa82b8 | ||
|
|
ac61ef1f81 | ||
|
|
924c421b75 | ||
|
|
71262d18a0 | ||
|
|
9645660d87 | ||
|
|
f18487ea68 | ||
|
|
13a955d45a | ||
|
|
7a06c72534 | ||
|
|
cdb572f347 | ||
|
|
8f44b06244 | ||
|
|
e8b81c1ff6 | ||
|
|
ab443fa50f | ||
|
|
25d55fec24 | ||
|
|
61f8b5c7f4 | ||
|
|
7c4714288d | ||
|
|
b6e393eabb | ||
|
|
d18aeb9918 | ||
|
|
6596afc562 | ||
|
|
587f76415b | ||
|
|
665aee6eb0 | ||
|
|
5e505c1240 | ||
|
|
e948f89625 | ||
|
|
f42b91f414 | ||
|
|
3e8a34c5f3 | ||
|
|
1101310845 | ||
|
|
0745028c06 | ||
|
|
94bda6d0f8 | ||
|
|
915d03a66a | ||
|
|
1422b440e4 | ||
|
|
95ad87d840 | ||
|
|
7357419f6f | ||
|
|
e07ebc21b9 | ||
|
|
8e5404a268 | ||
|
|
04fc729a5a | ||
|
|
8818a98230 | ||
|
|
d3efa3afa6 | ||
|
|
4414879b3f | ||
|
|
3c7aac59e9 | ||
|
|
41cd40a55b | ||
|
|
a0e8111b3a | ||
|
|
8f07ee5bf7 | ||
|
|
43da235d15 | ||
|
|
3252de19a3 | ||
|
|
fd3bd062fe | ||
|
|
029d447d98 | ||
|
|
8e5fac9fb3 | ||
|
|
30c0bcc910 | ||
|
|
1a4ba9b689 | ||
|
|
4de8191e27 | ||
|
|
472ca5a16b | ||
|
|
dab626031b | ||
|
|
913dded766 | ||
|
|
a36b7ce01a | ||
|
|
e4be336630 | ||
|
|
cae13df2c7 | ||
|
|
81796db6e5 | ||
|
|
ba3553854e | ||
|
|
c386d1af01 | ||
|
|
9566075dee | ||
|
|
9916b361e4 | ||
|
|
b2d7d797d9 | ||
|
|
7076afecfb | ||
|
|
e385b9f708 | ||
|
|
2b9b02aeea | ||
|
|
009b5e5ff1 | ||
|
|
7c310e7e46 | ||
|
|
bd0db57768 | ||
|
|
bb8ecccc31 | ||
|
|
ffd5817749 | ||
|
|
1a68236c3c | ||
|
|
c057bab493 | ||
|
|
59340c7cff | ||
|
|
aebb18da99 | ||
|
|
ce60335a60 | ||
|
|
307acdd9d1 | ||
|
|
d51e257904 | ||
|
|
07a3e83dc6 | ||
|
|
38f58b168a | ||
|
|
34abca5ff1 | ||
|
|
145764a921 | ||
|
|
9bbe573335 | ||
|
|
c5d5694f24 | ||
|
|
ab194a0e80 | ||
|
|
749944fc25 | ||
|
|
3cffc5538a | ||
|
|
6d7908e1f8 | ||
|
|
965b34318f | ||
|
|
3bb9eb9765 | ||
|
|
bd39595917 | ||
|
|
81e16a9cdf | ||
|
|
c38c8bcff2 | ||
|
|
7633af8ff2 | ||
|
|
94c0ebd897 | ||
|
|
7b3db4bae4 | ||
|
|
b1d95cac7f | ||
|
|
3f297a8afa | ||
|
|
af111a9625 | ||
|
|
96f715b62b | ||
|
|
33b4e38fc5 | ||
|
|
27e4ae9892 | ||
|
|
f434d8b066 | ||
|
|
43d471f93d | ||
|
|
3794f69cad | ||
|
|
cf4cd311b3 | ||
|
|
275326eaa6 | ||
|
|
526f8be676 | ||
|
|
0c392d5302 | ||
|
|
e71a2603bd | ||
|
|
5aea527962 | ||
|
|
05b3e97a0e | ||
|
|
243190491b | ||
|
|
7213dcf124 | ||
|
|
e90569bdcc | ||
|
|
404e27ab71 | ||
|
|
5af6d534df | ||
|
|
65410aabad | ||
|
|
2e78ea62b6 | ||
|
|
201461918d | ||
|
|
3efe0c7835 | ||
|
|
e3d453e397 | ||
|
|
c01818f57b | ||
|
|
f5e3d104e2 | ||
|
|
ba9dca4b05 | ||
|
|
efb7da316a | ||
|
|
895e142e2c | ||
|
|
f1ffadd39c | ||
|
|
8d4a1ff320 | ||
|
|
1f0e541743 | ||
|
|
adb7563ccb | ||
|
|
10917161b0 |
@@ -1,56 +0,0 @@
|
||||
version: "2"
|
||||
plugins:
|
||||
rubocop:
|
||||
enabled: true
|
||||
channel: "rubocop-1-12"
|
||||
config:
|
||||
file: ".rubocop.yml"
|
||||
scss-lint:
|
||||
enabled: true
|
||||
checks:
|
||||
ImportantRule:
|
||||
enabled: false
|
||||
VendorPrefix:
|
||||
enabled: false
|
||||
LeadingZero:
|
||||
enabled: false
|
||||
PropertySortOrder:
|
||||
enabled: false
|
||||
StringQuotes:
|
||||
enabled: false
|
||||
DeclarationOrder:
|
||||
enabled: false
|
||||
NestingDepth:
|
||||
enabled: false
|
||||
|
||||
duplication:
|
||||
enabled: true
|
||||
exclude_patterns:
|
||||
- "db/**"
|
||||
- "config/initializers/active_record_postgresql_referential_integrity_patch.rb"
|
||||
checks:
|
||||
argument-count:
|
||||
enabled: false
|
||||
complex-logic:
|
||||
enabled: false
|
||||
file-lines:
|
||||
enabled: false
|
||||
method-complexity:
|
||||
enabled: false
|
||||
method-count:
|
||||
enabled: false
|
||||
method-lines:
|
||||
enabled: false
|
||||
nested-control-flow:
|
||||
enabled: false
|
||||
return-statements:
|
||||
enabled: false
|
||||
similar-code:
|
||||
enabled: false
|
||||
identical-code:
|
||||
enabled: false
|
||||
exclude_patterns:
|
||||
- "spec/**/*"
|
||||
- "vendor/**/*"
|
||||
- "app/assets/javascripts/shared/*"
|
||||
- "app/assets/javascripts/jquery-migrate-1.0.0.js"
|
||||
25
.github/dependabot.yml
vendored
25
.github/dependabot.yml
vendored
@@ -4,7 +4,28 @@
|
||||
# Most of the configuration here is not used for security updates though.
|
||||
|
||||
version: 2
|
||||
|
||||
multi-ecosystem-groups:
|
||||
turbo_power:
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
updates:
|
||||
- package-ecosystem: "bundler"
|
||||
directory: "/"
|
||||
patterns: ["turbo_power"]
|
||||
multi-ecosystem-group: "turbo_power"
|
||||
|
||||
# Only specific requirements are specified in Gemfile, so don't touch it.
|
||||
versioning-strategy: lockfile-only
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
patterns: ["turbo_power"]
|
||||
multi-ecosystem-group: "turbo_power"
|
||||
|
||||
# Only specific requirements are specified in package.json, so don't touch it.
|
||||
versioning-strategy: lockfile-only
|
||||
|
||||
- package-ecosystem: "bundler"
|
||||
directory: "/"
|
||||
@@ -19,5 +40,5 @@ updates:
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
# All versions are specified in package.json, so please update them.
|
||||
versioning-strategy: increase
|
||||
# Only specific requirements are specified in package.json, so don't touch it.
|
||||
versioning-strategy: lockfile-only
|
||||
|
||||
24
.github/workflows/linters.yml
vendored
24
.github/workflows/linters.yml
vendored
@@ -2,10 +2,9 @@ name: Linters
|
||||
on: [pull_request]
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
checks: write # to post check annotations
|
||||
jobs:
|
||||
lint:
|
||||
name: prettier and rubocop
|
||||
name: reviewdog
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -22,21 +21,10 @@ jobs:
|
||||
|
||||
- run: git show --no-patch # the commit being tested (which is often a merge due to actions/checkout@v3)
|
||||
|
||||
- name: prettier
|
||||
uses: EPMatt/reviewdog-action-prettier@v1
|
||||
- uses: reviewdog/action-setup@v1
|
||||
with:
|
||||
github_token: ${{ secrets.github_token }}
|
||||
reporter: github-pr-check
|
||||
level: error
|
||||
fail_on_error: true
|
||||
reviewdog_version: v0.21.0
|
||||
|
||||
- name: rubocop
|
||||
uses: reviewdog/action-rubocop@v2
|
||||
with:
|
||||
rubocop_version: gemfile
|
||||
rubocop_extensions: rubocop-rails:gemfile rubocop-rspec:gemfile
|
||||
reporter: github-pr-check
|
||||
level: error
|
||||
filter_mode: nofilter
|
||||
use_bundler: true
|
||||
fail_level: any
|
||||
- run: ./script/reviewdog.sh
|
||||
env:
|
||||
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.github_token }}
|
||||
|
||||
@@ -2,19 +2,12 @@
|
||||
# frameworks such as Jekyll/Middleman
|
||||
skip_frontmatter: false
|
||||
|
||||
inherits_from: .haml-lint_todo.yml
|
||||
|
||||
linters:
|
||||
AltText:
|
||||
enabled: false
|
||||
|
||||
ClassAttributeWithStaticValue:
|
||||
enabled: true
|
||||
|
||||
ClassesBeforeIds:
|
||||
enabled: true
|
||||
|
||||
ConsecutiveComments:
|
||||
enabled: true
|
||||
|
||||
ConsecutiveSilentScripts:
|
||||
enabled: true
|
||||
max_consecutive: 2
|
||||
@@ -32,7 +25,6 @@ linters:
|
||||
enabled: true
|
||||
|
||||
LineLength:
|
||||
enabled: true
|
||||
max: 80
|
||||
|
||||
MultilinePipe:
|
||||
@@ -47,24 +39,11 @@ linters:
|
||||
RuboCop:
|
||||
enabled: false
|
||||
|
||||
RubyComments:
|
||||
enabled: true
|
||||
|
||||
SpaceBeforeScript:
|
||||
enabled: true
|
||||
|
||||
SpaceInsideHashAttributes:
|
||||
enabled: true
|
||||
style: no_space
|
||||
|
||||
TagName:
|
||||
enabled: true
|
||||
|
||||
TrailingWhitespace:
|
||||
enabled: true
|
||||
|
||||
UnnecessaryInterpolation:
|
||||
enabled: true
|
||||
|
||||
UnnecessaryStringOutput:
|
||||
enabled: true
|
||||
|
||||
153
.haml-lint_todo.yml
Normal file
153
.haml-lint_todo.yml
Normal file
@@ -0,0 +1,153 @@
|
||||
# This configuration was generated by
|
||||
# `haml-lint --auto-gen-config`
|
||||
# on 2025-10-30 09:19:50 +0100 using Haml-Lint version 0.66.0.
|
||||
# The point is for the user to remove these configuration records
|
||||
# one by one as the lints are removed from the code base.
|
||||
# Note that changes in the inspected code, or installation of new
|
||||
# versions of Haml-Lint, may require this file to be generated again.
|
||||
|
||||
linters:
|
||||
|
||||
# Offense count: 35
|
||||
ClassAttributeWithStaticValue:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 77
|
||||
ClassesBeforeIds:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 18
|
||||
ConsecutiveComments:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 22
|
||||
ConsecutiveSilentScripts:
|
||||
exclude:
|
||||
- "app/views/admin/contents/_fieldset.html.haml"
|
||||
- "app/views/admin/enterprises/form/_tag_rules.html.haml"
|
||||
- "app/views/admin/order_cycles/edit.html.haml"
|
||||
- "app/views/admin/products_v3/product_preview.turbo_stream.haml"
|
||||
- "app/views/admin/reports/_date_range_form.html.haml"
|
||||
- "app/views/checkout/_details.html.haml"
|
||||
- "app/views/checkout/_payment.html.haml"
|
||||
- "app/views/spree/admin/adjustments/_adjustments_table.html.haml"
|
||||
- "app/views/spree/admin/orders/customer_details/_address_form.html.haml"
|
||||
- "app/views/spree/admin/tax_categories/index.html.haml"
|
||||
- "app/views/spree/admin/users/index.html.haml"
|
||||
|
||||
# Offense count: 14
|
||||
FinalNewline:
|
||||
exclude:
|
||||
- "app/assets/javascripts/templates/shared/question_mark_with_tooltip.html.haml"
|
||||
- "app/views/admin/enterprises/form/_social.html.haml"
|
||||
- "app/views/admin/json/_injection_ams.html.haml"
|
||||
- "app/views/admin/order_cycles/_date_time_warning_modal_content.html.haml"
|
||||
- "app/views/admin/order_cycles/edit.html.haml"
|
||||
- "app/views/admin/product_import/_ams_data.html.haml"
|
||||
- "app/views/admin/reports/_row_group.haml"
|
||||
- "app/views/admin/reports/filters/_enterprise_fee_summary.html.haml"
|
||||
- "app/views/admin/reports/filters/_users_and_enterprises.html.haml"
|
||||
- "app/views/shop/_blocked_cookies.html.haml"
|
||||
- "app/views/spree/admin/orders/_invoice/_order_note.html.haml"
|
||||
- "app/views/spree/admin/orders/invoice4.html.haml"
|
||||
- "app/views/spree/admin/taxons/destroy_taxon.turbo_stream.haml"
|
||||
- "app/views/spree/admin/users/_email_confirmation.html.haml"
|
||||
|
||||
# Offense count: 130
|
||||
IdNames:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 5
|
||||
Indentation:
|
||||
exclude:
|
||||
- "app/views/admin/products_v3/clone.turbo_stream.haml"
|
||||
- "app/views/admin/products_v3/destroy_product_variant.turbo_stream.haml"
|
||||
- "app/views/spree/admin/taxons/destroy_taxon.turbo_stream.haml"
|
||||
|
||||
# Offense count: 191
|
||||
InlineStyles:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 589
|
||||
InstanceVariables:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 2
|
||||
LeadingCommentSpace:
|
||||
exclude:
|
||||
- "app/views/admin/reports/_row_group.haml"
|
||||
|
||||
# Offense count: 2331
|
||||
LineLength:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 1
|
||||
MultilinePipe:
|
||||
exclude:
|
||||
- "app/views/admin/reports/_rendering_options.html.haml"
|
||||
|
||||
# Offense count: 2
|
||||
MultilineScript:
|
||||
exclude:
|
||||
- "app/views/admin/products_v3/product_preview.turbo_stream.haml"
|
||||
- "app/views/checkout/_voucher_section.html.haml"
|
||||
|
||||
# Offense count: 2
|
||||
RepeatedId:
|
||||
exclude:
|
||||
- "app/assets/javascripts/templates/admin/save_bar.html.haml"
|
||||
|
||||
# Offense count: 24
|
||||
RubyComments:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 104
|
||||
SpaceBeforeScript:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 3345
|
||||
SpaceInsideHashAttributes:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 22
|
||||
TrailingEmptyLines:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 73
|
||||
TrailingWhitespace:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 13
|
||||
UnnecessaryInterpolation:
|
||||
exclude:
|
||||
- "app/components/example_component/example_component.html.haml"
|
||||
- "app/views/admin/product_import/_entries_table.html.haml"
|
||||
- "app/views/admin/product_import/import.html.haml"
|
||||
- "app/views/admin/variant_overrides/_filters.html.haml"
|
||||
- "app/views/registration/steps/_introduction.html.haml"
|
||||
- "app/views/spree/order_mailer/_shipping.html.haml"
|
||||
- "app/views/spree/order_mailer/invoice_email.html.haml"
|
||||
- "app/views/spree/shared/_shipment_delivery_details.html.haml"
|
||||
- "app/views/spree/shared/_shipment_pickup_details.html.haml"
|
||||
|
||||
# Offense count: 68
|
||||
UnnecessaryStringOutput:
|
||||
enabled: false
|
||||
|
||||
# Offense count: 14
|
||||
ViewLength:
|
||||
exclude:
|
||||
- "app/assets/javascripts/templates/admin/panels/enterprise_package.html.haml"
|
||||
- "app/views/admin/customers/index.html.haml"
|
||||
- "app/views/admin/enterprises/_new_form.html.haml"
|
||||
- "app/views/admin/enterprises/form/_shop_preferences.html.haml"
|
||||
- "app/views/admin/product_import/_import_review.html.haml"
|
||||
- "app/views/admin/products_v3/product_preview.turbo_stream.haml"
|
||||
- "app/views/checkout/_details.html.haml"
|
||||
- "app/views/groups/show.html.haml"
|
||||
- "app/views/producer_mailer/order_cycle_report.html.haml"
|
||||
- "app/views/shared/_footer.html.haml"
|
||||
- "app/views/spree/admin/orders/bulk_management.html.haml"
|
||||
- "app/views/spree/admin/orders/invoice4.html.haml"
|
||||
- "app/views/spree/admin/products/new.html.haml"
|
||||
- "app/views/spree/admin/variants/_form.html.haml"
|
||||
@@ -1,6 +0,0 @@
|
||||
rubocop:
|
||||
config_file: .rubocop_styleguide.yml
|
||||
scss:
|
||||
config_file: .scss-lint.yml
|
||||
haml:
|
||||
config_file: .haml-lint.yml
|
||||
@@ -1,6 +1,6 @@
|
||||
# This configuration was generated by
|
||||
# `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 1400 --no-auto-gen-timestamp`
|
||||
# using RuboCop version 1.81.6.
|
||||
# using RuboCop version 1.81.7.
|
||||
# The point is for the user to remove these configuration records
|
||||
# one by one as the offenses are removed from the code base.
|
||||
# Note that changes in the inspected code, or installation of new
|
||||
@@ -80,7 +80,7 @@ Metrics/BlockNesting:
|
||||
Exclude:
|
||||
- 'app/models/spree/payment/processing.rb'
|
||||
|
||||
# Offense count: 48
|
||||
# Offense count: 49
|
||||
# Configuration parameters: CountComments, Max, CountAsOne.
|
||||
Metrics/ClassLength:
|
||||
Exclude:
|
||||
@@ -122,6 +122,7 @@ Metrics/ClassLength:
|
||||
- 'app/services/order_cycles/form_service.rb'
|
||||
- 'app/services/orders/sync_service.rb'
|
||||
- 'app/services/permissions/order.rb'
|
||||
- 'app/services/products_renderer.rb'
|
||||
- 'app/services/sets/product_set.rb'
|
||||
- 'engines/order_management/app/services/order_management/order/updater.rb'
|
||||
- 'lib/open_food_network/enterprise_fee_calculator.rb'
|
||||
@@ -133,7 +134,7 @@ Metrics/ClassLength:
|
||||
- 'lib/reporting/reports/enterprise_fee_summary/scope.rb'
|
||||
- 'lib/reporting/reports/xero_invoices/base.rb'
|
||||
|
||||
# Offense count: 35
|
||||
# Offense count: 37
|
||||
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
||||
Metrics/CyclomaticComplexity:
|
||||
Exclude:
|
||||
@@ -234,7 +235,7 @@ Naming/MethodParameterName:
|
||||
Exclude:
|
||||
- 'engines/dfc_provider/lib/dfc_provider/catalog_item.rb'
|
||||
|
||||
# Offense count: 59
|
||||
# Offense count: 60
|
||||
# Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates.
|
||||
# AllowedMethods: call
|
||||
# WaywardPredicates: nonzero?
|
||||
@@ -335,6 +336,24 @@ Rails/OrderArguments:
|
||||
- 'spec/services/orders/generate_invoice_service_spec.rb'
|
||||
- 'spec/system/admin/order_cycles/simple_spec.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Rails/Presence:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/enterprises_controller.rb'
|
||||
- 'app/models/spree/product.rb'
|
||||
|
||||
# Offense count: 6
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: Severity.
|
||||
Rails/RedirectBackOrTo:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/order_cycles_controller.rb'
|
||||
- 'app/controllers/locales_controller.rb'
|
||||
- 'app/controllers/spree/admin/invoices_controller.rb'
|
||||
- 'app/controllers/spree/admin/orders_controller.rb'
|
||||
- 'app/controllers/spree/admin/return_authorizations_controller.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: TransactionMethods.
|
||||
Rails/TransactionExitStatement:
|
||||
|
||||
@@ -1 +1 @@
|
||||
3.1.7
|
||||
3.2.9
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
scss_files: 'app/assets/stylesheets/**/*.css.scss'
|
||||
|
||||
exclude: 'app/assets/stylesheets/shared/**'
|
||||
|
||||
linters:
|
||||
ImportantRule:
|
||||
enabled: false
|
||||
VendorPrefix:
|
||||
enabled: false
|
||||
LeadingZero:
|
||||
enabled: false
|
||||
PropertySortOrder:
|
||||
enabled: false
|
||||
StringQuotes:
|
||||
enabled: false
|
||||
DeclarationOrder:
|
||||
enabled: false
|
||||
NestingDepth:
|
||||
enabled: false
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM ruby:3.1.7-alpine3.19 AS base
|
||||
FROM ruby:3.2.9-alpine3.19 AS base
|
||||
ENV LANG=C.UTF-8 \
|
||||
LC_ALL=C.UTF-8 \
|
||||
TZ=Europe/London \
|
||||
|
||||
14
Gemfile
14
Gemfile
@@ -1,6 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
source 'https://rubygems.org'
|
||||
source 'https://gem.coop'
|
||||
git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
|
||||
|
||||
ruby File.read('.ruby-version').chomp
|
||||
@@ -14,8 +14,8 @@ gem "active_storage_validations"
|
||||
gem "aws-sdk-s3", require: false
|
||||
gem "image_processing"
|
||||
|
||||
gem 'activemerchant', '>= 1.78.0'
|
||||
gem 'angular-rails-templates', '>= 0.3.0'
|
||||
gem 'activemerchant'
|
||||
gem 'angular-rails-templates'
|
||||
gem 'ransack', '~> 4.1.0'
|
||||
gem 'responders'
|
||||
gem 'webpacker', '~> 5'
|
||||
@@ -43,7 +43,7 @@ gem 'web', path: './engines/web'
|
||||
|
||||
gem "activerecord-postgresql-adapter"
|
||||
gem "arel-helpers", "~> 2.12"
|
||||
gem "pg", "~> 1.2.3"
|
||||
gem "pg"
|
||||
|
||||
gem 'acts_as_list', '1.0.4'
|
||||
gem 'cancancan', '~> 1.15.0'
|
||||
@@ -57,7 +57,7 @@ gem 'state_machines-activerecord'
|
||||
gem 'stringex', '~> 2.8.5', require: false
|
||||
|
||||
gem 'paypal-sdk-merchant', '1.117.2'
|
||||
gem 'stripe'
|
||||
gem 'stripe', '~> 13'
|
||||
|
||||
gem 'devise'
|
||||
gem 'devise-encryptable'
|
||||
@@ -185,11 +185,11 @@ group :test do
|
||||
end
|
||||
|
||||
group :development do
|
||||
gem 'debugger-linecache'
|
||||
gem 'foreman'
|
||||
gem 'haml_lint', require: false
|
||||
gem 'i18n-tasks'
|
||||
gem 'listen'
|
||||
gem 'pry', '~> 0.13.0'
|
||||
gem 'pry'
|
||||
gem 'query_count'
|
||||
gem 'rails-erd'
|
||||
gem 'rubocop'
|
||||
|
||||
468
Gemfile.lock
468
Gemfile.lock
@@ -46,38 +46,39 @@ PATH
|
||||
web (0.0.1)
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
remote: https://gem.coop/
|
||||
specs:
|
||||
Ascii85 (2.0.1)
|
||||
actioncable (7.1.5.2)
|
||||
actionpack (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
actioncable (7.1.6)
|
||||
actionpack (= 7.1.6)
|
||||
activesupport (= 7.1.6)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
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)
|
||||
actionmailbox (7.1.6)
|
||||
actionpack (= 7.1.6)
|
||||
activejob (= 7.1.6)
|
||||
activerecord (= 7.1.6)
|
||||
activestorage (= 7.1.6)
|
||||
activesupport (= 7.1.6)
|
||||
mail (>= 2.7.1)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
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)
|
||||
actionmailer (7.1.6)
|
||||
actionpack (= 7.1.6)
|
||||
actionview (= 7.1.6)
|
||||
activejob (= 7.1.6)
|
||||
activesupport (= 7.1.6)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
rails-dom-testing (~> 2.2)
|
||||
actionpack (7.1.5.2)
|
||||
actionview (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
actionpack (7.1.6)
|
||||
actionview (= 7.1.6)
|
||||
activesupport (= 7.1.6)
|
||||
cgi
|
||||
nokogiri (>= 1.8.5)
|
||||
racc
|
||||
rack (>= 2.2.4)
|
||||
@@ -87,16 +88,17 @@ GEM
|
||||
rails-html-sanitizer (~> 1.6)
|
||||
actionpack-action_caching (1.2.2)
|
||||
actionpack (>= 4.0.0)
|
||||
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)
|
||||
actiontext (7.1.6)
|
||||
actionpack (= 7.1.6)
|
||||
activerecord (= 7.1.6)
|
||||
activestorage (= 7.1.6)
|
||||
activesupport (= 7.1.6)
|
||||
globalid (>= 0.6.0)
|
||||
nokogiri (>= 1.8.5)
|
||||
actionview (7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
actionview (7.1.6)
|
||||
activesupport (= 7.1.6)
|
||||
builder (~> 3.1)
|
||||
cgi
|
||||
erubi (~> 1.11)
|
||||
rails-dom-testing (~> 2.2)
|
||||
rails-html-sanitizer (~> 1.6)
|
||||
@@ -107,39 +109,38 @@ GEM
|
||||
activemodel (>= 5.2.0)
|
||||
activestorage (>= 5.2.0)
|
||||
activesupport (>= 5.2.0)
|
||||
activejob (7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
activejob (7.1.6)
|
||||
activesupport (= 7.1.6)
|
||||
globalid (>= 0.3.6)
|
||||
activemerchant (1.133.0)
|
||||
activemerchant (1.137.0)
|
||||
activesupport (>= 4.2)
|
||||
builder (>= 2.1.2, < 4.0.0)
|
||||
i18n (>= 0.6.9)
|
||||
nokogiri (~> 1.4)
|
||||
rexml (~> 3.2.5)
|
||||
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)
|
||||
rexml (~> 3.3, >= 3.3.4)
|
||||
activemodel (7.1.6)
|
||||
activesupport (= 7.1.6)
|
||||
activerecord (7.1.6)
|
||||
activemodel (= 7.1.6)
|
||||
activesupport (= 7.1.6)
|
||||
timeout (>= 0.4.0)
|
||||
activerecord-import (2.2.0)
|
||||
activerecord (>= 4.2)
|
||||
activerecord-postgresql-adapter (0.0.1)
|
||||
pg
|
||||
activerecord-session_store (2.1.0)
|
||||
actionpack (>= 6.1)
|
||||
activerecord (>= 6.1)
|
||||
activerecord-session_store (2.2.0)
|
||||
actionpack (>= 7.0)
|
||||
activerecord (>= 7.0)
|
||||
cgi (>= 0.3.6)
|
||||
multi_json (~> 1.11, >= 1.11.2)
|
||||
rack (>= 2.0.8, < 4)
|
||||
railties (>= 6.1)
|
||||
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)
|
||||
railties (>= 7.0)
|
||||
activestorage (7.1.6)
|
||||
actionpack (= 7.1.6)
|
||||
activejob (= 7.1.6)
|
||||
activerecord (= 7.1.6)
|
||||
activesupport (= 7.1.6)
|
||||
marcel (~> 1.0)
|
||||
activesupport (7.1.5.2)
|
||||
activesupport (7.1.6)
|
||||
base64
|
||||
benchmark (>= 0.3)
|
||||
bigdecimal
|
||||
@@ -152,53 +153,57 @@ GEM
|
||||
mutex_m
|
||||
securerandom (>= 0.3)
|
||||
tzinfo (~> 2.0)
|
||||
acts-as-taggable-on (10.0.0)
|
||||
activerecord (>= 6.1, < 7.2)
|
||||
acts-as-taggable-on (13.0.0)
|
||||
activerecord (>= 7.1, < 8.2)
|
||||
zeitwerk (>= 2.4, < 3.0)
|
||||
acts_as_list (1.0.4)
|
||||
activerecord (>= 4.2)
|
||||
addressable (2.8.7)
|
||||
public_suffix (>= 2.0.2, < 7.0)
|
||||
aes_key_wrap (1.1.0)
|
||||
afm (0.2.2)
|
||||
angular-rails-templates (1.2.1)
|
||||
railties (>= 5.0, < 7.2)
|
||||
angular-rails-templates (1.4.0)
|
||||
railties (>= 5.0, < 8.2)
|
||||
sprockets (>= 3.0, < 5)
|
||||
sprockets-rails
|
||||
tilt
|
||||
angular_rails_csrf (6.0.0)
|
||||
railties (>= 3, < 8)
|
||||
angular_rails_csrf (7.0.2)
|
||||
railties (>= 3, < 9)
|
||||
angularjs-file-upload-rails (2.4.1)
|
||||
angularjs-rails (1.8.0)
|
||||
arel-helpers (2.14.0)
|
||||
activerecord (>= 3.1.0, < 8)
|
||||
arel-helpers (2.17.0)
|
||||
activerecord (>= 3.1.0)
|
||||
ast (2.4.3)
|
||||
attr_required (1.0.2)
|
||||
aws-eventstream (1.3.0)
|
||||
aws-partitions (1.929.0)
|
||||
aws-sdk-core (3.196.1)
|
||||
aws-eventstream (1.4.0)
|
||||
aws-partitions (1.1191.0)
|
||||
aws-sdk-core (3.239.2)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.651.0)
|
||||
aws-sigv4 (~> 1.8)
|
||||
aws-partitions (~> 1, >= 1.992.0)
|
||||
aws-sigv4 (~> 1.9)
|
||||
base64
|
||||
bigdecimal
|
||||
jmespath (~> 1, >= 1.6.1)
|
||||
aws-sdk-kms (1.81.0)
|
||||
aws-sdk-core (~> 3, >= 3.193.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sdk-s3 (1.151.0)
|
||||
aws-sdk-core (~> 3, >= 3.194.0)
|
||||
logger
|
||||
aws-sdk-kms (1.118.0)
|
||||
aws-sdk-core (~> 3, >= 3.239.1)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sdk-s3 (1.206.0)
|
||||
aws-sdk-core (~> 3, >= 3.234.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.8)
|
||||
aws-sigv4 (1.8.0)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sigv4 (1.12.1)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
base64 (0.3.0)
|
||||
bcp47_spec (0.2.1)
|
||||
bcrypt (3.1.20)
|
||||
benchmark (0.5.0)
|
||||
bigdecimal (3.3.1)
|
||||
bindata (2.5.0)
|
||||
bindata (2.5.1)
|
||||
bindex (0.8.1)
|
||||
bootsnap (1.18.3)
|
||||
bootsnap (1.19.0)
|
||||
msgpack (~> 1.2)
|
||||
bugsnag (6.26.4)
|
||||
bugsnag (6.28.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
builder (3.3.0)
|
||||
bullet (8.0.8)
|
||||
@@ -223,7 +228,7 @@ GEM
|
||||
xpath (~> 3.2)
|
||||
capybara-shadowdom (0.3.0)
|
||||
capybara
|
||||
caxlsx (3.3.0)
|
||||
caxlsx (4.0.0)
|
||||
htmlentities (~> 4.3, >= 4.3.4)
|
||||
marcel (~> 1.0)
|
||||
nokogiri (~> 1.10, >= 1.10.4)
|
||||
@@ -240,35 +245,34 @@ GEM
|
||||
coffee-script-source
|
||||
execjs
|
||||
coffee-script-source (1.12.2)
|
||||
combine_pdf (1.0.26)
|
||||
combine_pdf (1.0.31)
|
||||
matrix
|
||||
ruby-rc4 (>= 0.1.5)
|
||||
concurrent-ruby (1.3.5)
|
||||
connection_pool (2.5.4)
|
||||
connection_pool (2.5.5)
|
||||
cookiejar (0.3.4)
|
||||
crack (1.0.0)
|
||||
bigdecimal
|
||||
rexml
|
||||
crass (1.0.6)
|
||||
css_parser (1.17.1)
|
||||
css_parser (1.21.1)
|
||||
addressable
|
||||
csv (3.3.0)
|
||||
csv (3.3.5)
|
||||
cuprite (0.15)
|
||||
capybara (~> 3.0)
|
||||
ferrum (~> 0.14.0)
|
||||
database_cleaner (2.0.2)
|
||||
database_cleaner (2.1.0)
|
||||
database_cleaner-active_record (>= 2, < 3)
|
||||
database_cleaner-active_record (2.1.0)
|
||||
database_cleaner-active_record (2.2.2)
|
||||
activerecord (>= 5.a)
|
||||
database_cleaner-core (~> 2.0.0)
|
||||
database_cleaner-core (~> 2.0)
|
||||
database_cleaner-core (2.0.1)
|
||||
datafoodconsortium-connector (1.1.0)
|
||||
datafoodconsortium-connector (1.2.0)
|
||||
virtual_assembly-semantizer (~> 1.0, >= 1.0.5)
|
||||
date (3.4.1)
|
||||
debug (1.9.2)
|
||||
date (3.5.0)
|
||||
debug (1.11.0)
|
||||
irb (~> 1.10)
|
||||
reline (>= 0.3.8)
|
||||
debugger-linecache (1.2.0)
|
||||
devise (4.9.4)
|
||||
bcrypt (~> 3.0)
|
||||
orm_adapter (~> 0.1)
|
||||
@@ -277,14 +281,15 @@ GEM
|
||||
warden (~> 1.2.3)
|
||||
devise-encryptable (0.2.0)
|
||||
devise (>= 2.1.0)
|
||||
devise-i18n (1.12.1)
|
||||
devise-i18n (1.15.0)
|
||||
devise (>= 4.9.0)
|
||||
rails-i18n
|
||||
devise-token_authenticatable (1.1.0)
|
||||
devise (>= 4.0.0, < 5.0.0)
|
||||
diff-lcs (1.6.2)
|
||||
digest (3.2.0)
|
||||
digest (3.2.1)
|
||||
docile (1.4.1)
|
||||
dotenv (3.1.2)
|
||||
dotenv (3.1.8)
|
||||
drb (2.2.3)
|
||||
em-http-request (1.1.7)
|
||||
addressable (>= 2.3.4)
|
||||
@@ -299,8 +304,7 @@ GEM
|
||||
eventmachine (>= 1.0.0.beta.1)
|
||||
email_validator (2.2.4)
|
||||
activemodel
|
||||
erb (4.0.4)
|
||||
cgi (>= 0.3.3)
|
||||
erb (6.0.0)
|
||||
erubi (1.13.1)
|
||||
et-orbi (1.3.0)
|
||||
tzinfo
|
||||
@@ -315,29 +319,29 @@ GEM
|
||||
railties (>= 5.0.0)
|
||||
faraday (2.9.0)
|
||||
faraday-net_http (>= 2.0, < 3.2)
|
||||
faraday-follow_redirects (0.3.0)
|
||||
faraday-follow_redirects (0.4.0)
|
||||
faraday (>= 1, < 3)
|
||||
faraday-net_http (3.1.0)
|
||||
faraday-net_http (3.1.1)
|
||||
net-http
|
||||
ferrum (0.14)
|
||||
addressable (~> 2.5)
|
||||
concurrent-ruby (~> 1.1)
|
||||
webrick (~> 1.7)
|
||||
websocket-driver (>= 0.6, < 0.8)
|
||||
ffaker (2.23.0)
|
||||
ffi (1.16.3)
|
||||
ffaker (2.25.0)
|
||||
ffi (1.17.2)
|
||||
flipper (1.3.6)
|
||||
concurrent-ruby (< 2)
|
||||
flipper-active_record (1.3.0)
|
||||
activerecord (>= 4.2, < 8)
|
||||
flipper (~> 1.3.0)
|
||||
flipper-ui (1.3.0)
|
||||
flipper-active_record (1.3.6)
|
||||
activerecord (>= 4.2, < 9)
|
||||
flipper (~> 1.3.6)
|
||||
flipper-ui (1.3.6)
|
||||
erubi (>= 1.0.0, < 2.0.0)
|
||||
flipper (~> 1.3.0)
|
||||
flipper (~> 1.3.6)
|
||||
rack (>= 1.4, < 4)
|
||||
rack-protection (>= 1.5.3, < 5.0.0)
|
||||
rack-session (>= 1.0.2, < 3.0.0)
|
||||
sanitize (< 7)
|
||||
sanitize (< 8)
|
||||
fog-aws (2.0.1)
|
||||
fog-core (~> 1.38)
|
||||
fog-json (~> 1.0)
|
||||
@@ -353,7 +357,8 @@ GEM
|
||||
fog-xml (0.1.3)
|
||||
fog-core
|
||||
nokogiri (>= 1.5.11, < 2.0.0)
|
||||
foreman (0.88.1)
|
||||
foreman (0.90.0)
|
||||
thor (~> 1.4)
|
||||
formatador (0.2.5)
|
||||
fugit (1.11.1)
|
||||
et-orbi (~> 1, >= 1.2.11)
|
||||
@@ -361,30 +366,36 @@ GEM
|
||||
fuubar (2.5.1)
|
||||
rspec-core (~> 3.0)
|
||||
ruby-progressbar (~> 1.4)
|
||||
geocoder (1.8.3)
|
||||
geocoder (1.8.6)
|
||||
base64 (>= 0.1.0)
|
||||
csv (>= 3.0.0)
|
||||
globalid (1.2.1)
|
||||
globalid (1.3.0)
|
||||
activesupport (>= 6.1)
|
||||
gmaps4rails (2.1.2)
|
||||
good_migrations (0.2.1)
|
||||
good_migrations (0.3.1)
|
||||
activerecord (>= 3.1)
|
||||
railties (>= 3.1)
|
||||
haml (6.3.0)
|
||||
temple (>= 0.8.2)
|
||||
thor
|
||||
tilt
|
||||
haml_lint (0.67.0)
|
||||
haml (>= 5.0)
|
||||
parallel (~> 1.10)
|
||||
rainbow
|
||||
rubocop (>= 1.0)
|
||||
sysexits (~> 1.1)
|
||||
hashdiff (1.2.1)
|
||||
hashery (2.1.2)
|
||||
hashie (5.0.0)
|
||||
highline (2.0.3)
|
||||
htmlentities (4.3.4)
|
||||
htmlentities (4.4.2)
|
||||
http_parser.rb (0.8.0)
|
||||
i18n (1.14.7)
|
||||
concurrent-ruby (~> 1.0)
|
||||
i18n-js (3.9.2)
|
||||
i18n (>= 0.6.6)
|
||||
i18n-tasks (1.0.14)
|
||||
i18n-tasks (1.0.15)
|
||||
activesupport (>= 4.0.2)
|
||||
ast (>= 2.1.0)
|
||||
erubi
|
||||
@@ -393,9 +404,10 @@ GEM
|
||||
parser (>= 3.2.2.1)
|
||||
rails-i18n
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
ruby-progressbar (~> 1.8, >= 1.8.1)
|
||||
terminal-table (>= 1.5.1)
|
||||
image_processing (1.12.2)
|
||||
mini_magick (>= 4.9.5, < 5)
|
||||
image_processing (1.14.0)
|
||||
mini_magick (>= 4.9.5, < 6)
|
||||
ruby-vips (>= 2.0.17, < 3)
|
||||
imagen (0.2.0)
|
||||
parser (>= 2.5, != 2.5.1.1)
|
||||
@@ -405,7 +417,7 @@ GEM
|
||||
rails (>= 5.2)
|
||||
io-console (0.8.1)
|
||||
ipaddress (0.8.3)
|
||||
irb (1.15.2)
|
||||
irb (1.15.3)
|
||||
pp (>= 0.6.0)
|
||||
rdoc (>= 4.0.0)
|
||||
reline (>= 0.4.2)
|
||||
@@ -418,7 +430,7 @@ GEM
|
||||
railties (>= 3.2.16)
|
||||
json (2.15.2)
|
||||
json-canonicalization (1.0.0)
|
||||
json-jwt (1.16.6)
|
||||
json-jwt (1.17.0)
|
||||
activesupport (>= 4.2)
|
||||
aes_key_wrap
|
||||
base64
|
||||
@@ -440,7 +452,7 @@ GEM
|
||||
rspec (>= 2.0, < 4.0)
|
||||
jsonapi-serializer (2.2.0)
|
||||
activesupport (>= 4.2)
|
||||
jwt (2.8.1)
|
||||
jwt (2.10.2)
|
||||
base64
|
||||
knapsack_pro (8.4.0)
|
||||
rake
|
||||
@@ -459,13 +471,14 @@ GEM
|
||||
loofah (2.24.1)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.12.0)
|
||||
mail (2.8.1)
|
||||
mail (2.9.0)
|
||||
logger
|
||||
mini_mime (>= 0.1.1)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
marcel (1.0.4)
|
||||
matrix (0.4.2)
|
||||
marcel (1.1.0)
|
||||
matrix (0.4.3)
|
||||
method_source (1.1.0)
|
||||
mime-types (3.7.0)
|
||||
logger
|
||||
@@ -474,31 +487,32 @@ GEM
|
||||
mimemagic (0.4.3)
|
||||
nokogiri (~> 1)
|
||||
rake
|
||||
mini_magick (4.13.2)
|
||||
mini_magick (5.3.1)
|
||||
logger
|
||||
mini_mime (1.1.5)
|
||||
mini_portile2 (2.8.6)
|
||||
minitest (5.26.0)
|
||||
minitest (5.26.2)
|
||||
monetize (1.13.0)
|
||||
money (~> 6.12)
|
||||
money (6.16.0)
|
||||
i18n (>= 0.6.4, <= 2)
|
||||
msgpack (1.7.2)
|
||||
multi_json (1.15.0)
|
||||
msgpack (1.8.0)
|
||||
multi_json (1.17.0)
|
||||
multi_xml (0.6.0)
|
||||
mutex_m (0.3.0)
|
||||
net-http (0.4.1)
|
||||
net-http (0.7.0)
|
||||
uri
|
||||
net-imap (0.4.20)
|
||||
net-imap (0.5.12)
|
||||
date
|
||||
net-protocol
|
||||
net-pop (0.1.2)
|
||||
net-protocol
|
||||
net-protocol (0.2.2)
|
||||
timeout
|
||||
net-smtp (0.5.0)
|
||||
net-smtp (0.5.1)
|
||||
net-protocol
|
||||
newrelic_rpm (9.22.0)
|
||||
nio4r (2.7.1)
|
||||
newrelic_rpm (9.23.0)
|
||||
nio4r (2.7.5)
|
||||
nokogiri (1.18.10)
|
||||
mini_portile2 (~> 2.8.2)
|
||||
racc (~> 1.4)
|
||||
@@ -511,17 +525,18 @@ GEM
|
||||
multi_xml (~> 0.5)
|
||||
rack (>= 1.2, < 4)
|
||||
observer (0.1.2)
|
||||
omniauth (2.1.2)
|
||||
omniauth (2.1.4)
|
||||
hashie (>= 3.4.6)
|
||||
logger
|
||||
rack (>= 2.2.3)
|
||||
rack-protection
|
||||
omniauth-rails_csrf_protection (1.0.2)
|
||||
actionpack (>= 4.2)
|
||||
omniauth (~> 2.0)
|
||||
omniauth_openid_connect (0.7.1)
|
||||
omniauth_openid_connect (0.8.0)
|
||||
omniauth (>= 1.9, < 3)
|
||||
openid_connect (~> 2.2)
|
||||
openid_connect (2.3.0)
|
||||
openid_connect (2.3.1)
|
||||
activemodel
|
||||
attr_required (>= 1.0.0)
|
||||
email_validator
|
||||
@@ -536,12 +551,12 @@ GEM
|
||||
webfinger (~> 2.0)
|
||||
orm_adapter (0.5.0)
|
||||
ostruct (0.6.1)
|
||||
pagy (9.3.4)
|
||||
paper_trail (15.1.0)
|
||||
activerecord (>= 6.1)
|
||||
pagy (9.4.0)
|
||||
paper_trail (17.0.0)
|
||||
activerecord (>= 7.1)
|
||||
request_store (~> 1.4)
|
||||
parallel (1.27.0)
|
||||
paranoia (2.6.3)
|
||||
paranoia (2.6.4)
|
||||
activerecord (>= 5.1, < 7.2)
|
||||
parser (3.3.10.0)
|
||||
ast (~> 2.4.1)
|
||||
@@ -557,13 +572,13 @@ GEM
|
||||
hashery (~> 2.0)
|
||||
ruby-rc4
|
||||
ttfunk
|
||||
pg (1.2.3)
|
||||
pp (0.6.2)
|
||||
pg (1.6.2)
|
||||
pp (0.6.3)
|
||||
prettyprint
|
||||
prettyprint (0.2.0)
|
||||
prism (1.6.0)
|
||||
private_address_check (0.5.0)
|
||||
pry (0.13.1)
|
||||
pry (0.15.2)
|
||||
coderay (~> 1.1)
|
||||
method_source (~> 1.0)
|
||||
psych (5.2.6)
|
||||
@@ -585,10 +600,10 @@ GEM
|
||||
railties (>= 4.2)
|
||||
raabro (1.4.0)
|
||||
racc (1.8.1)
|
||||
rack (2.2.20)
|
||||
rack (2.2.21)
|
||||
rack-mini-profiler (2.3.4)
|
||||
rack (>= 1.2.0)
|
||||
rack-oauth2 (2.2.1)
|
||||
rack-oauth2 (2.3.0)
|
||||
activesupport
|
||||
attr_required
|
||||
faraday (~> 2.0)
|
||||
@@ -609,20 +624,20 @@ GEM
|
||||
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)
|
||||
rails (7.1.6)
|
||||
actioncable (= 7.1.6)
|
||||
actionmailbox (= 7.1.6)
|
||||
actionmailer (= 7.1.6)
|
||||
actionpack (= 7.1.6)
|
||||
actiontext (= 7.1.6)
|
||||
actionview (= 7.1.6)
|
||||
activejob (= 7.1.6)
|
||||
activemodel (= 7.1.6)
|
||||
activerecord (= 7.1.6)
|
||||
activestorage (= 7.1.6)
|
||||
activesupport (= 7.1.6)
|
||||
bundler (>= 1.15.0)
|
||||
railties (= 7.1.5.2)
|
||||
railties (= 7.1.6)
|
||||
rails-controller-testing (1.0.5)
|
||||
actionpack (>= 5.0.1.rc1)
|
||||
actionview (>= 5.0.1.rc1)
|
||||
@@ -642,16 +657,18 @@ GEM
|
||||
rails-i18n (7.0.10)
|
||||
i18n (>= 0.7, < 2)
|
||||
railties (>= 6.0.0, < 8)
|
||||
railties (7.1.5.2)
|
||||
actionpack (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
railties (7.1.6)
|
||||
actionpack (= 7.1.6)
|
||||
activesupport (= 7.1.6)
|
||||
cgi
|
||||
irb
|
||||
rackup (>= 1.0.0)
|
||||
rake (>= 12.2)
|
||||
thor (~> 1.0, >= 1.2.2)
|
||||
tsort (>= 0.2)
|
||||
zeitwerk (~> 2.6)
|
||||
rainbow (3.1.1)
|
||||
rake (13.3.0)
|
||||
rake (13.3.1)
|
||||
ransack (4.1.1)
|
||||
activerecord (>= 6.1.5)
|
||||
activesupport (>= 6.1.5)
|
||||
@@ -659,34 +676,38 @@ GEM
|
||||
rb-fsevent (0.11.2)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
rdf (3.3.2)
|
||||
rdf (3.3.4)
|
||||
bcp47_spec (~> 0.2)
|
||||
bigdecimal (~> 3.1, >= 3.1.5)
|
||||
link_header (~> 0.0, >= 0.0.8)
|
||||
rdoc (6.15.0)
|
||||
logger (~> 1.5)
|
||||
ostruct (~> 0.6)
|
||||
readline (~> 0.0)
|
||||
rdoc (6.16.0)
|
||||
erb
|
||||
psych (>= 4.0.0)
|
||||
tsort
|
||||
redcarpet (3.6.0)
|
||||
readline (0.0.4)
|
||||
reline
|
||||
redcarpet (3.6.1)
|
||||
redis (5.4.1)
|
||||
redis-client (>= 0.22.0)
|
||||
redis-client (0.26.1)
|
||||
connection_pool
|
||||
regexp_parser (2.11.3)
|
||||
reline (0.6.2)
|
||||
reline (0.6.3)
|
||||
io-console (~> 0.5)
|
||||
request_store (1.5.1)
|
||||
request_store (1.7.0)
|
||||
rack (>= 1.4)
|
||||
responders (3.1.1)
|
||||
actionpack (>= 5.2)
|
||||
railties (>= 5.2)
|
||||
rexml (3.2.9)
|
||||
strscan
|
||||
rexml (3.4.4)
|
||||
roadie (5.2.1)
|
||||
css_parser (~> 1.4)
|
||||
nokogiri (~> 1.15)
|
||||
roadie-rails (3.2.0)
|
||||
railties (>= 5.1, < 8.0)
|
||||
roadie-rails (3.4.0)
|
||||
railties (>= 5.1, < 8.2)
|
||||
roadie (~> 5.0)
|
||||
rodf (1.2.0)
|
||||
builder (>= 3.0)
|
||||
@@ -720,22 +741,22 @@ GEM
|
||||
activesupport
|
||||
rspec
|
||||
rspec-support (3.13.6)
|
||||
rswag (2.16.0)
|
||||
rswag-api (= 2.16.0)
|
||||
rswag-specs (= 2.16.0)
|
||||
rswag-ui (= 2.16.0)
|
||||
rswag-api (2.16.0)
|
||||
activesupport (>= 5.2, < 8.1)
|
||||
railties (>= 5.2, < 8.1)
|
||||
rswag-specs (2.16.0)
|
||||
activesupport (>= 5.2, < 8.1)
|
||||
json-schema (>= 2.2, < 6.0)
|
||||
railties (>= 5.2, < 8.1)
|
||||
rswag (2.17.0)
|
||||
rswag-api (= 2.17.0)
|
||||
rswag-specs (= 2.17.0)
|
||||
rswag-ui (= 2.17.0)
|
||||
rswag-api (2.17.0)
|
||||
activesupport (>= 5.2, < 8.2)
|
||||
railties (>= 5.2, < 8.2)
|
||||
rswag-specs (2.17.0)
|
||||
activesupport (>= 5.2, < 8.2)
|
||||
json-schema (>= 2.2, < 7.0)
|
||||
railties (>= 5.2, < 8.2)
|
||||
rspec-core (>= 2.14)
|
||||
rswag-ui (2.16.0)
|
||||
actionpack (>= 5.2, < 8.1)
|
||||
railties (>= 5.2, < 8.1)
|
||||
rubocop (1.81.6)
|
||||
rswag-ui (2.17.0)
|
||||
actionpack (>= 5.2, < 8.2)
|
||||
railties (>= 5.2, < 8.2)
|
||||
rubocop (1.81.7)
|
||||
json (~> 2.3)
|
||||
language_server-protocol (~> 3.17.0.2)
|
||||
lint_roller (~> 1.1.0)
|
||||
@@ -746,25 +767,25 @@ GEM
|
||||
rubocop-ast (>= 1.47.1, < 2.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 2.4.0, < 4.0)
|
||||
rubocop-ast (1.47.1)
|
||||
rubocop-ast (1.48.0)
|
||||
parser (>= 3.3.7.2)
|
||||
prism (~> 1.4)
|
||||
rubocop-capybara (2.22.1)
|
||||
lint_roller (~> 1.1)
|
||||
rubocop (~> 1.72, >= 1.72.1)
|
||||
rubocop-factory_bot (2.27.1)
|
||||
rubocop-factory_bot (2.28.0)
|
||||
lint_roller (~> 1.1)
|
||||
rubocop (~> 1.72, >= 1.72.1)
|
||||
rubocop-rails (2.33.4)
|
||||
rubocop-rails (2.34.2)
|
||||
activesupport (>= 4.2.0)
|
||||
lint_roller (~> 1.1)
|
||||
rack (>= 1.1)
|
||||
rubocop (>= 1.75.0, < 2.0)
|
||||
rubocop-ast (>= 1.44.0, < 2.0)
|
||||
rubocop-rspec (3.7.0)
|
||||
rubocop-rspec (3.8.0)
|
||||
lint_roller (~> 1.1)
|
||||
rubocop (~> 1.72, >= 1.72.1)
|
||||
rubocop-rspec_rails (2.31.0)
|
||||
rubocop (~> 1.81)
|
||||
rubocop-rspec_rails (2.32.0)
|
||||
lint_roller (~> 1.1)
|
||||
rubocop (~> 1.72, >= 1.72.1)
|
||||
rubocop-rspec (~> 3.5)
|
||||
@@ -772,15 +793,16 @@ GEM
|
||||
rexml
|
||||
ruby-progressbar (1.13.0)
|
||||
ruby-rc4 (0.1.5)
|
||||
ruby-vips (2.1.4)
|
||||
ruby-vips (2.2.5)
|
||||
ffi (~> 1.12)
|
||||
rubyzip (2.3.2)
|
||||
logger
|
||||
rubyzip (2.4.1)
|
||||
rufus-scheduler (3.8.2)
|
||||
fugit (~> 1.1, >= 1.1.6)
|
||||
rugged (1.9.0)
|
||||
sanitize (6.1.0)
|
||||
sanitize (7.0.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.12.0)
|
||||
nokogiri (>= 1.16.8)
|
||||
sass (3.4.25)
|
||||
sass-rails (5.0.8)
|
||||
railties (>= 5.2.0)
|
||||
@@ -791,8 +813,8 @@ GEM
|
||||
sd_notify (0.1.1)
|
||||
securerandom (0.4.1)
|
||||
semantic_range (3.0.0)
|
||||
shoulda-matchers (6.2.0)
|
||||
activesupport (>= 5.2.0)
|
||||
shoulda-matchers (7.0.1)
|
||||
activesupport (>= 7.1)
|
||||
sidekiq (7.2.4)
|
||||
concurrent-ruby (< 2)
|
||||
connection_pool (>= 2.3.0)
|
||||
@@ -808,10 +830,11 @@ GEM
|
||||
simplecov_json_formatter (~> 0.1)
|
||||
simplecov-html (0.13.2)
|
||||
simplecov_json_formatter (0.1.4)
|
||||
spreadsheet_architect (5.0.0)
|
||||
caxlsx (>= 3.3.0, < 4)
|
||||
rodf (>= 1.0.0, < 2)
|
||||
spring (4.2.1)
|
||||
spreadsheet_architect (5.1.0)
|
||||
caxlsx (<= 4.0)
|
||||
csv
|
||||
rodf
|
||||
spring (4.4.0)
|
||||
spring-commands-rspec (1.0.4)
|
||||
spring (>= 0.9.1)
|
||||
spring-commands-rubocop (0.4.0)
|
||||
@@ -820,14 +843,14 @@ GEM
|
||||
base64
|
||||
concurrent-ruby (~> 1.0)
|
||||
rack (> 1, < 3)
|
||||
sprockets-rails (3.4.2)
|
||||
actionpack (>= 5.2)
|
||||
activesupport (>= 5.2)
|
||||
sprockets-rails (3.5.2)
|
||||
actionpack (>= 6.1)
|
||||
activesupport (>= 6.1)
|
||||
sprockets (>= 3.0.0)
|
||||
state_machines (0.20.0)
|
||||
state_machines-activemodel (0.10.0)
|
||||
state_machines (0.100.4)
|
||||
state_machines-activemodel (0.31.0)
|
||||
activemodel (>= 7.1)
|
||||
state_machines (>= 0.10.0)
|
||||
state_machines (>= 0.31.0)
|
||||
state_machines-activerecord (0.31.0)
|
||||
activerecord (>= 7.1)
|
||||
state_machines-activemodel (>= 0.10.0)
|
||||
@@ -844,33 +867,32 @@ GEM
|
||||
railties (>= 5.2)
|
||||
redis (>= 4.0, < 6.0)
|
||||
stringex (2.8.6)
|
||||
stringio (3.1.7)
|
||||
stripe (11.1.0)
|
||||
strscan (3.1.5)
|
||||
stringio (3.1.8)
|
||||
stripe (13.5.1)
|
||||
swd (2.0.3)
|
||||
activesupport (>= 3)
|
||||
attr_required (>= 0.0.5)
|
||||
faraday (~> 2.0)
|
||||
faraday-follow_redirects
|
||||
sysexits (1.2.0)
|
||||
temple (0.8.2)
|
||||
terminal-table (4.0.0)
|
||||
unicode-display_width (>= 1.1.1, < 4)
|
||||
thor (1.4.0)
|
||||
thread-local (1.1.0)
|
||||
tilt (2.3.0)
|
||||
timeout (0.4.3)
|
||||
tilt (2.6.1)
|
||||
timeout (0.4.4)
|
||||
tsort (0.2.0)
|
||||
ttfunk (1.8.0)
|
||||
bigdecimal (~> 3.1)
|
||||
turbo-rails (2.0.5)
|
||||
actionpack (>= 6.0.0)
|
||||
activejob (>= 6.0.0)
|
||||
railties (>= 6.0.0)
|
||||
turbo_power (0.6.2)
|
||||
turbo-rails (2.0.20)
|
||||
actionpack (>= 7.1.0)
|
||||
railties (>= 7.1.0)
|
||||
turbo_power (0.7.0)
|
||||
turbo-rails (>= 1.3.0)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
undercover (0.8.1)
|
||||
undercover (0.8.3)
|
||||
base64
|
||||
bigdecimal
|
||||
imagen (>= 0.2.0)
|
||||
@@ -882,7 +904,7 @@ GEM
|
||||
unicode-emoji (~> 4.1)
|
||||
unicode-emoji (4.1.0)
|
||||
uniform_notifier (1.17.0)
|
||||
uri (0.13.2)
|
||||
uri (1.1.1)
|
||||
valid_email2 (5.2.3)
|
||||
activemodel (>= 3.2)
|
||||
mail (~> 2.5)
|
||||
@@ -892,10 +914,10 @@ GEM
|
||||
validates_lengths_from_database (0.8.0)
|
||||
activerecord (>= 4)
|
||||
vcr (6.2.0)
|
||||
view_component (3.12.1)
|
||||
activesupport (>= 5.2.0, < 8.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
method_source (~> 1.0)
|
||||
view_component (4.1.1)
|
||||
actionview (>= 7.1.0, < 8.2)
|
||||
activesupport (>= 7.1.0, < 8.2)
|
||||
concurrent-ruby (~> 1)
|
||||
view_component_reflex (3.1.14.pre9)
|
||||
rails (>= 5.2, < 8.0)
|
||||
stimulus_reflex (>= 3.5.0.pre2)
|
||||
@@ -922,19 +944,21 @@ GEM
|
||||
rack-proxy (>= 0.6.1)
|
||||
railties (>= 5.2)
|
||||
semantic_range (>= 2.3.0)
|
||||
webrick (1.9.1)
|
||||
websocket-driver (0.7.6)
|
||||
webrick (1.9.2)
|
||||
websocket-driver (0.7.7)
|
||||
base64
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.5)
|
||||
whenever (1.0.0)
|
||||
whenever (1.1.0)
|
||||
chronic (>= 0.6.3)
|
||||
wicked_pdf (2.8.1)
|
||||
wicked_pdf (2.8.2)
|
||||
activesupport
|
||||
ostruct
|
||||
wkhtmltopdf-binary (0.12.6.10)
|
||||
xml-simple (1.1.8)
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
zeitwerk (2.6.18)
|
||||
zeitwerk (2.7.3)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
@@ -943,13 +967,13 @@ DEPENDENCIES
|
||||
actionpack-action_caching
|
||||
active_model_serializers (= 0.8.4)
|
||||
active_storage_validations
|
||||
activemerchant (>= 1.78.0)
|
||||
activemerchant
|
||||
activerecord-import
|
||||
activerecord-postgresql-adapter
|
||||
activerecord-session_store
|
||||
acts-as-taggable-on
|
||||
acts_as_list (= 1.0.4)
|
||||
angular-rails-templates (>= 0.3.0)
|
||||
angular-rails-templates
|
||||
angular_rails_csrf
|
||||
angularjs-file-upload-rails (~> 2.4.1)
|
||||
angularjs-rails (= 1.8.0)
|
||||
@@ -971,7 +995,6 @@ DEPENDENCIES
|
||||
datafoodconsortium-connector
|
||||
db2fog!
|
||||
debug (>= 1.0.0)
|
||||
debugger-linecache
|
||||
devise
|
||||
devise-encryptable
|
||||
devise-i18n
|
||||
@@ -992,6 +1015,7 @@ DEPENDENCIES
|
||||
gmaps4rails
|
||||
good_migrations
|
||||
haml
|
||||
haml_lint
|
||||
highline (= 2.0.3)
|
||||
i18n
|
||||
i18n-js (~> 3.9.0)
|
||||
@@ -1023,9 +1047,9 @@ DEPENDENCIES
|
||||
paranoia (~> 2.4)
|
||||
paypal-sdk-merchant (= 1.117.2)
|
||||
pdf-reader
|
||||
pg (~> 1.2.3)
|
||||
pg
|
||||
private_address_check
|
||||
pry (~> 0.13.0)
|
||||
pry
|
||||
puffing-billy
|
||||
puma
|
||||
query_count
|
||||
@@ -1069,7 +1093,7 @@ DEPENDENCIES
|
||||
stimulus_reflex
|
||||
stimulus_reflex_testing!
|
||||
stringex (~> 2.8.5)
|
||||
stripe
|
||||
stripe (~> 13)
|
||||
turbo-rails
|
||||
turbo_power
|
||||
undercover
|
||||
@@ -1087,7 +1111,7 @@ DEPENDENCIES
|
||||
wkhtmltopdf-binary
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.7p261
|
||||
ruby 3.2.9p265
|
||||
|
||||
BUNDLED WITH
|
||||
2.4.3
|
||||
2.4.19
|
||||
|
||||
@@ -11,6 +11,9 @@ angular.module("admin.customers").controller "customersCtrl", ($scope, $q, $filt
|
||||
$scope.confirmRefresh = (event) ->
|
||||
event.preventDefault() unless pendingChanges.unsavedCount() == 0 || confirm(t("unsaved_changes_warning"))
|
||||
|
||||
$scope.hasUnsavedChanges = ->
|
||||
pendingChanges.yes()
|
||||
|
||||
$scope.$watch "shop_id", ->
|
||||
if $scope.shop_id?
|
||||
CurrentShop.shop = $filter('filter')($scope.shops, {id: parseInt($scope.shop_id)}, true)[0]
|
||||
|
||||
@@ -4,15 +4,16 @@ angular.module("admin.indexUtils").directive "objForUpdate", (switchClass, pendi
|
||||
type: "@objForUpdate"
|
||||
attr: "@attrForUpdate"
|
||||
link: (scope, element, attrs) ->
|
||||
scope.savedValue = scope.object()[scope.attr]
|
||||
scope.savedValue = scope.object()[scope.attr] || ""
|
||||
|
||||
scope.$watch "object().#{scope.attr}", (value) ->
|
||||
if value == scope.savedValue
|
||||
strValue = value || ""
|
||||
if strValue == scope.savedValue
|
||||
pendingChanges.remove(scope.object().id, scope.attr)
|
||||
scope.clear()
|
||||
else
|
||||
scope.pending()
|
||||
addPendingChange(scope.attr, value ? "")
|
||||
addPendingChange(scope.attr, strValue)
|
||||
|
||||
scope.reset = (value) ->
|
||||
scope.savedValue = value
|
||||
|
||||
@@ -16,7 +16,10 @@ angular.module("admin.indexUtils").factory "pendingChanges", ($q, resources, Sta
|
||||
remove: (id, attr) =>
|
||||
if @pendingChanges.hasOwnProperty("#{id}")
|
||||
delete @pendingChanges["#{id}"]["#{attr}"]
|
||||
delete @pendingChanges["#{id}"] if @changeCount( @pendingChanges["#{id}"] ) < 1
|
||||
|
||||
if @changeCount( @pendingChanges["#{id}"] ) < 1
|
||||
delete @pendingChanges["#{id}"]
|
||||
StatusMessage.clear()
|
||||
|
||||
submitAll: (form=null) =>
|
||||
all = []
|
||||
@@ -47,5 +50,8 @@ angular.module("admin.indexUtils").factory "pendingChanges", ($q, resources, Sta
|
||||
unsavedCount: ->
|
||||
Object.keys(@pendingChanges).length
|
||||
|
||||
yes: ->
|
||||
@unsavedCount() > 0
|
||||
|
||||
changeCount: (objectChanges) ->
|
||||
Object.keys(objectChanges).length
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("admin.indexUtils").factory "switchClass", ($timeout) ->
|
||||
angular.module("admin.indexUtils").factory "switchClass", ($timeout, StatusMessage) ->
|
||||
return (element, classToAdd, removeClasses, timeout) ->
|
||||
$timeout.cancel element.timeout if element.timeout
|
||||
element.removeClass className for className in removeClasses
|
||||
@@ -7,4 +7,6 @@ angular.module("admin.indexUtils").factory "switchClass", ($timeout) ->
|
||||
if timeout && intRegex.test(timeout)
|
||||
element.timeout = $timeout(->
|
||||
element.removeClass classToAdd
|
||||
StatusMessage.clear()
|
||||
, timeout, true)
|
||||
element
|
||||
|
||||
@@ -5,16 +5,19 @@ class TagListInputComponent < ViewComponent::Base
|
||||
placeholder: I18n.t("components.tag_list_input.default_placeholder"),
|
||||
only_one: false,
|
||||
aria_label: nil,
|
||||
hidden_field_data_options: {})
|
||||
hidden_field_data_options: {},
|
||||
autocomplete_url: "")
|
||||
@name = name
|
||||
@tags = tags
|
||||
@placeholder = placeholder
|
||||
@only_one = only_one
|
||||
@aria_label_option = aria_label ? { 'aria-label': aria_label } : {}
|
||||
@hidden_field_data_options = hidden_field_data_options
|
||||
@autocomplete_url = autocomplete_url
|
||||
end
|
||||
|
||||
attr_reader :name, :tags, :placeholder, :only_one, :aria_label_option, :hidden_field_data_options
|
||||
attr_reader :name, :tags, :placeholder, :only_one, :aria_label_option,
|
||||
:hidden_field_data_options, :autocomplete_url
|
||||
|
||||
private
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
%div{ "data-controller": "tag-list-input", "data-tag-list-input-only-one-value": "#{only_one}" }
|
||||
%div{ "data-controller": "tag-list-input", "data-tag-list-input-only-one-value": "#{only_one}", "data-tag-list-input-url-value": autocomplete_url, "data-action": "autocomplete.change->tag-list-input#addTag" }
|
||||
.tags-input
|
||||
.tags
|
||||
- # We use display:none instead of hidden field, so changes to the value can be picked up by the bulkFormController
|
||||
@@ -16,4 +16,12 @@
|
||||
%span=tag
|
||||
%a.remove-button{ "data-action": "click->tag-list-input#removeTag" }
|
||||
×
|
||||
= text_field_tag "variant_add_tag", nil, class: "input", placeholder: placeholder, "data-action": "keydown.enter->tag-list-input#addTag keyup->tag-list-input#filterInput blur->tag-list-input#addTag", "data-tag-list-input-target": "newTag", **aria_label_option, style: "display: #{display};"
|
||||
= text_field_tag("variant_add_tag",
|
||||
nil,
|
||||
{ class: "input",
|
||||
placeholder: placeholder,
|
||||
"data-action": "keydown.enter->tag-list-input#keyboardAddTag keyup->tag-list-input#filterInput blur->tag-list-input#onBlur focus->tag-list-input#onInputChange",
|
||||
"data-tag-list-input-target": "input",
|
||||
**aria_label_option,
|
||||
style: "display: #{display};"})
|
||||
%ul.suggestion-list{ "data-tag-list-input-target": "results" , hidden: true }
|
||||
|
||||
@@ -67,4 +67,35 @@
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
ul.suggestion-list {
|
||||
margin-top: 5px;
|
||||
padding: 5px 0;
|
||||
z-index: $tag-drop-down-z-index;
|
||||
width: fit-content;
|
||||
background-color: #fff;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
box-shadow: $shadow-dropdown;
|
||||
list-style-type: none;
|
||||
max-height: 280px;
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
|
||||
li.suggestion-item {
|
||||
padding: 5px 10px;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
width: stretch;
|
||||
|
||||
&.active,
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background-color: $color-link-visited;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
import { Controller } from "stimulus";
|
||||
import { Autocomplete } from "stimulus-autocomplete";
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["tagList", "newTag", "template", "list"];
|
||||
// Extend the stimulus-autocomplete controller, so we can load tag with existing rules
|
||||
// The autocomplete functionality is only loaded if the url value is set
|
||||
// For more informatioon on "stimulus-autocomplete", see:
|
||||
// https://github.com/afcapel/stimulus-autocomplete/tree/main
|
||||
//
|
||||
export default class extends Autocomplete {
|
||||
static targets = ["tagList", "input", "template", "list"];
|
||||
static values = { onlyOne: Boolean };
|
||||
|
||||
addTag(event) {
|
||||
// prevent hotkey form submitting the form (default action for "enter" key)
|
||||
event.preventDefault();
|
||||
connect() {
|
||||
// Don't start autocomplete controller if we don't have an url
|
||||
if (this.urlValue.length == 0) return;
|
||||
|
||||
const newTagName = this.newTagTarget.value.trim().replaceAll(" ", "-");
|
||||
super.connect();
|
||||
}
|
||||
|
||||
addTag(event) {
|
||||
const newTagName = this.inputTarget.value.trim().replaceAll(" ", "-");
|
||||
if (newTagName.length == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -18,7 +27,7 @@ export default class extends Controller {
|
||||
const index = tags.indexOf(newTagName);
|
||||
if (index != -1) {
|
||||
// highlight the value in red
|
||||
this.newTagTarget.classList.add("tag-error");
|
||||
this.inputTarget.classList.add("tag-error");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -38,14 +47,23 @@ export default class extends Controller {
|
||||
this.listTarget.appendChild(newTagElement);
|
||||
|
||||
// Clear new tag value
|
||||
this.newTagTarget.value = "";
|
||||
this.inputTarget.value = "";
|
||||
|
||||
// hide tag input if limited to one tag
|
||||
if (this.tagListTarget.value.split(",").length == 1 && this.onlyOneValue == true) {
|
||||
this.newTagTarget.style.display = "none";
|
||||
this.inputTarget.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
keyboardAddTag(event) {
|
||||
// prevent hotkey form submitting the form (default action for "enter" key)
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
this.addTag();
|
||||
}
|
||||
|
||||
removeTag(event) {
|
||||
// Text to remove
|
||||
const tagName = event.srcElement.previousElementSibling.textContent;
|
||||
@@ -62,14 +80,14 @@ export default class extends Controller {
|
||||
|
||||
// Make sure the tag input is displayed
|
||||
if (this.tagListTarget.value.length == 0) {
|
||||
this.newTagTarget.style.display = "block";
|
||||
this.inputTarget.style.display = "block";
|
||||
}
|
||||
}
|
||||
|
||||
filterInput(event) {
|
||||
// clear error class if key is not enter
|
||||
if (event.key !== "Enter") {
|
||||
this.newTagTarget.classList.remove("tag-error");
|
||||
this.inputTarget.classList.remove("tag-error");
|
||||
}
|
||||
|
||||
// Strip comma from tag name
|
||||
@@ -77,4 +95,53 @@ export default class extends Controller {
|
||||
event.srcElement.value = event.srcElement.value.replace(",", "");
|
||||
}
|
||||
}
|
||||
|
||||
// Add tag if we don't have an autocomplete list open
|
||||
onBlur() {
|
||||
// check if we have any autocomplete results
|
||||
if (this.resultsTarget.childElementCount == 0) this.addTag();
|
||||
}
|
||||
|
||||
// Override original to add tag filtering
|
||||
replaceResults(html) {
|
||||
const filteredHtml = this.#filterResults(html);
|
||||
|
||||
// Don't show result if we don't have anything to show
|
||||
if (filteredHtml.length == 0) return;
|
||||
|
||||
super.replaceResults(filteredHtml);
|
||||
}
|
||||
|
||||
// Override original to all empty query, which will return all existing tags
|
||||
onInputChange = () => {
|
||||
if (this.urlValue.length == 0) return;
|
||||
|
||||
if (this.hasHiddenTarget) this.hiddenTarget.value = "";
|
||||
|
||||
const query = this.inputTarget.value.trim();
|
||||
if (query.length >= this.minLengthValue) {
|
||||
this.fetchResults(query);
|
||||
} else {
|
||||
this.hideAndRemoveOptions();
|
||||
}
|
||||
};
|
||||
|
||||
//private
|
||||
|
||||
#filterResults(html) {
|
||||
const existingTags = this.tagListTarget.value.split(",");
|
||||
// Parse the HTML
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(html, "text/html");
|
||||
const lis = doc.getElementsByTagName("li");
|
||||
// Filter
|
||||
let filteredHtml = "";
|
||||
for (let li of lis) {
|
||||
if (!existingTags.includes(li.dataset.autocompleteValue)) {
|
||||
filteredHtml += li.outerHTML;
|
||||
}
|
||||
}
|
||||
|
||||
return filteredHtml;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,13 @@ class TagRuleFormComponent < ViewComponent::Base
|
||||
taggable: "variant",
|
||||
visibility_field: "preferred_matched_variants_visibility",
|
||||
}
|
||||
when "TagRule::FilterVariants"
|
||||
{
|
||||
text_top: t('components.tag_rule_form.tag_rules.variant_tagged_top'),
|
||||
text_bottom: t('components.tag_rule_form.tag_rules.variant_tagged_bottom'),
|
||||
taggable: "variant",
|
||||
visibility_field: "preferred_matched_variants_visibility",
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -51,6 +51,18 @@ module Admin
|
||||
end
|
||||
end
|
||||
|
||||
# copy of Admin::ResourceController without flash notice
|
||||
def update
|
||||
if @object.update(permitted_resource_params)
|
||||
respond_with(@object) do |format|
|
||||
format.html { redirect_to location_after_save }
|
||||
format.js { render layout: false }
|
||||
end
|
||||
else
|
||||
respond_with(@object)
|
||||
end
|
||||
end
|
||||
|
||||
# copy of Admin::ResourceController without flash notice
|
||||
def destroy
|
||||
if @object.destroy
|
||||
|
||||
@@ -15,8 +15,8 @@ module Admin
|
||||
def index
|
||||
# Fetch DFC catalog JSON for preview
|
||||
@catalog_url = params.require(:catalog_url).strip
|
||||
@catalog_json = api.call(@catalog_url)
|
||||
catalog = DfcCatalog.from_json(@catalog_json)
|
||||
@catalog_data = api.call(@catalog_url)
|
||||
catalog = DfcCatalog.from_json(@catalog_data)
|
||||
|
||||
# Render table and let user decide which ones to import.
|
||||
@items = list_products(catalog)
|
||||
|
||||
@@ -51,6 +51,7 @@ module Admin
|
||||
|
||||
load_tag_rule_types
|
||||
|
||||
load_tag_rules
|
||||
return unless params[:stimulus]
|
||||
|
||||
@enterprise.is_primary_producer = params[:is_primary_producer]
|
||||
@@ -84,6 +85,7 @@ module Admin
|
||||
end
|
||||
else
|
||||
load_tag_rule_types
|
||||
load_tag_rules
|
||||
respond_with(@object) do |format|
|
||||
format.json {
|
||||
render json: { errors: @object.errors.messages }, status: :unprocessable_entity
|
||||
@@ -398,9 +400,26 @@ module Admin
|
||||
[t(".form.tag_rules.show_hide_order_cycles"), "FilterOrderCycles"]
|
||||
]
|
||||
|
||||
return unless helpers.feature?(:inventory, @object)
|
||||
if helpers.feature?(:variant_tag, @object)
|
||||
@tag_rule_types.prepend([t(".form.tag_rules.show_hide_variants"), "FilterVariants"])
|
||||
elsif helpers.feature?(:inventory, @object)
|
||||
@tag_rule_types.prepend([t(".form.tag_rules.show_hide_variants"), "FilterProducts"])
|
||||
end
|
||||
end
|
||||
|
||||
@tag_rule_types.prepend([t(".form.tag_rules.show_hide_variants"), "FilterProducts"])
|
||||
def load_tag_rules
|
||||
if helpers.feature?(:variant_tag, @object)
|
||||
@default_rules = @enterprise.tag_rules.exclude_inventory.select(&:is_default)
|
||||
@rules = @enterprise.tag_rules.exclude_inventory.prioritised.reject(&:is_default)
|
||||
elsif helpers.feature?(:inventory, @object)
|
||||
@default_rules = @enterprise.tag_rules.exclude_variant.select(&:is_default)
|
||||
@rules = @enterprise.tag_rules.exclude_variant.prioritised.reject(&:is_default)
|
||||
else
|
||||
@default_rules =
|
||||
@enterprise.tag_rules.exclude_inventory.exclude_variant.select(&:is_default)
|
||||
@rules =
|
||||
@enterprise.tag_rules.exclude_inventory.exclude_variant.prioritised.reject(&:is_default)
|
||||
end
|
||||
end
|
||||
|
||||
def setup_property
|
||||
|
||||
@@ -49,7 +49,7 @@ module Admin
|
||||
errors: @importer.errors.full_messages
|
||||
}
|
||||
|
||||
if helpers.feature?(:inventory, *spree_current_user.enterprises)
|
||||
if helpers.inventory_enabled?(spree_current_user.enterprises)
|
||||
json[:results][:inventory_created] = @importer.inventory_created_count
|
||||
json[:results][:inventory_updated] = @importer.inventory_updated_count
|
||||
end
|
||||
@@ -175,7 +175,7 @@ module Admin
|
||||
|
||||
# Return an error if trying to import into inventories when inventory is disable
|
||||
def can_import_into_inventories?
|
||||
return true if helpers.feature?(:inventory, *spree_current_user.enterprises) ||
|
||||
return true if helpers.inventory_enabled?(spree_current_user.enterprises) ||
|
||||
params.dig(:settings, "import_into") != 'inventories'
|
||||
|
||||
redirect_to admin_product_import_url, notice: I18n.t(:product_import_inventory_disable)
|
||||
|
||||
@@ -11,7 +11,8 @@ module Admin
|
||||
def index
|
||||
fetch_products
|
||||
render "index",
|
||||
locals: { producers:, categories:, tax_category_options:, available_tags:, flash: }
|
||||
locals: { producer_options:, categories:, tax_category_options:, available_tags:,
|
||||
flash:, allowed_producers: }
|
||||
|
||||
session[:products_return_to_url] = request.url
|
||||
end
|
||||
@@ -32,7 +33,8 @@ module Admin
|
||||
|
||||
render "index", status: :unprocessable_entity,
|
||||
locals: {
|
||||
producers:, categories:, tax_category_options:, available_tags:, flash:
|
||||
producer_options:, categories:, tax_category_options:, available_tags:,
|
||||
allowed_producers:, flash:
|
||||
}
|
||||
end
|
||||
end
|
||||
@@ -78,27 +80,29 @@ module Admin
|
||||
end
|
||||
|
||||
def clone
|
||||
@product = Spree::Product.find(params[:id])
|
||||
authorize! :clone, @product
|
||||
product = Spree::Product.find(params[:id])
|
||||
authorize! :clone, product
|
||||
|
||||
status = :ok
|
||||
|
||||
begin
|
||||
@cloned_product = @product.duplicate
|
||||
cloned_product = product.duplicate
|
||||
flash.now[:success] = t('.success')
|
||||
|
||||
@product_index = "-#{@cloned_product.id}"
|
||||
@producer_options = producers
|
||||
@category_options = categories
|
||||
@tax_category_options = tax_category_options
|
||||
product_index = "-#{cloned_product.id}"
|
||||
rescue ActiveRecord::ActiveRecordError => e
|
||||
flash.now[:error] = clone_error_message(e)
|
||||
status = :unprocessable_entity
|
||||
@product_index = "-1" # Create a unique enough index
|
||||
product_index = "-1" # Create a unique enough index
|
||||
end
|
||||
|
||||
respond_with do |format|
|
||||
format.turbo_stream { render :clone, status: }
|
||||
format.turbo_stream {
|
||||
render :clone, status:,
|
||||
locals: { product:, cloned_product:, product_index:, producer_options:,
|
||||
category_options: categories, tax_category_options:,
|
||||
allowed_producers: }
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -124,18 +128,31 @@ module Admin
|
||||
@per_page = params[:per_page].presence || 15
|
||||
@q = params.permit(q: {})[:q] || { s: 'name asc' }
|
||||
|
||||
# Transform on_hand sorting to include backorderable_priority (on-demand) for proper ordering
|
||||
# Transform on_hand sorting to properly handle On-Demand products:
|
||||
# - On-Demand products should ignore on_hand completely and sort alphabetically.
|
||||
# - Non-On-Demand products should continue sorting by on_hand as usual.
|
||||
if @q[:s] == 'on_hand asc'
|
||||
@q[:s] = ['backorderable_priority asc', @q[:s]]
|
||||
@q[:s] = [
|
||||
'backorderable_priority asc',
|
||||
'backorderable_name asc',
|
||||
@q[:s]
|
||||
]
|
||||
elsif @q[:s] == 'on_hand desc'
|
||||
@q[:s] = ['backorderable_priority desc', @q[:s]]
|
||||
@q[:s] = [
|
||||
'backorderable_priority desc',
|
||||
'backorderable_name asc',
|
||||
@q[:s]
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
def producers
|
||||
producers = OpenFoodNetwork::Permissions.new(spree_current_user)
|
||||
def allowed_producers
|
||||
OpenFoodNetwork::Permissions.new(spree_current_user)
|
||||
.managed_product_enterprises.is_primary_producer.by_name
|
||||
producers.map { |p| [p.name, p.id] }
|
||||
end
|
||||
|
||||
def producer_options
|
||||
allowed_producers.map { |p| [p.name, p.id] }
|
||||
end
|
||||
|
||||
def categories
|
||||
@@ -173,6 +190,7 @@ module Admin
|
||||
product_query = product_query.select(
|
||||
Arel.sql('spree_products.*'),
|
||||
Spree::Product.backorderable_priority_sql,
|
||||
Spree::Product.backorderable_name_sql,
|
||||
Spree::Product.on_hand_sql
|
||||
)
|
||||
end
|
||||
|
||||
@@ -41,6 +41,7 @@ module Admin
|
||||
end
|
||||
end
|
||||
|
||||
# Used by the tag input autocomplete
|
||||
def map_by_tag
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
@@ -50,6 +51,26 @@ module Admin
|
||||
end
|
||||
end
|
||||
|
||||
# Use to populate autocomplete with available rule for the given tag/enterprise
|
||||
def variant_tag_rules
|
||||
tag_rules =
|
||||
TagRule.matching_variant_tag_rules_by_enterprises(params[:enterprise_id], params[:q])
|
||||
|
||||
@formatted_tag_rules = tag_rules.each_with_object({}) do |rule, mapping|
|
||||
rule.preferred_variant_tags.split(",").each do |tag|
|
||||
if mapping[tag]
|
||||
mapping[tag][:rules] += 1
|
||||
else
|
||||
mapping[tag] = { tag:, rules: 1 }
|
||||
end
|
||||
end
|
||||
end.values
|
||||
|
||||
respond_with do |format|
|
||||
format.html { render :variant_tag_rules, layout: false }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def collection_actions
|
||||
@@ -78,7 +99,7 @@ module Admin
|
||||
end
|
||||
|
||||
def permitted_tag_rule_type
|
||||
%w{FilterOrderCycles FilterPaymentMethods FilterProducts FilterShippingMethods}
|
||||
%w{FilterOrderCycles FilterPaymentMethods FilterProducts FilterShippingMethods FilterVariants}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -44,6 +44,8 @@ module Admin
|
||||
def load_data
|
||||
@hubs = OpenFoodNetwork::Permissions.new(spree_current_user).
|
||||
variant_override_hubs.by_name
|
||||
# Only display the ones with inventory enabled
|
||||
@hubs = @hubs.select { |p| helpers.feature?(:inventory, p) }
|
||||
|
||||
# Used in JS to look up the name of the producer of each product
|
||||
@producers = OpenFoodNetwork::Permissions.new(spree_current_user).
|
||||
|
||||
@@ -43,7 +43,7 @@ module Api
|
||||
@enterprise = Enterprise.find_by(permalink: params[:id]) || Enterprise.find(params[:id])
|
||||
authorize! :update, @enterprise
|
||||
|
||||
if params[:logo] && @enterprise.update( logo: params[:logo] )
|
||||
if params[:logo] && @enterprise.update!(logo: params[:logo])
|
||||
render(html: @enterprise.logo_url(:medium), status: :ok)
|
||||
elsif params[:promo] && @enterprise.update!( promo_image: params[:promo] )
|
||||
render(html: @enterprise.promo_image_url(:medium), status: :ok)
|
||||
|
||||
@@ -23,7 +23,8 @@ module Api
|
||||
order_cycle,
|
||||
customer,
|
||||
search_params,
|
||||
inventory_enabled:
|
||||
inventory_enabled:,
|
||||
variant_tag_enabled:
|
||||
).products_json
|
||||
|
||||
render plain: products
|
||||
@@ -96,13 +97,17 @@ module Api
|
||||
|
||||
def distributed_products
|
||||
OrderCycles::DistributedProductsService.new(
|
||||
distributor, order_cycle, customer, inventory_enabled:
|
||||
distributor, order_cycle, customer, inventory_enabled:, variant_tag_enabled:,
|
||||
).products_relation.pluck(:id)
|
||||
end
|
||||
|
||||
def inventory_enabled
|
||||
OpenFoodNetwork::FeatureToggle.enabled?(:inventory, distributor)
|
||||
end
|
||||
|
||||
def variant_tag_enabled
|
||||
OpenFoodNetwork::FeatureToggle.enabled?(:variant_tag, distributor)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,6 +8,10 @@ module Api
|
||||
include AddressTransformation
|
||||
include ExtraFields
|
||||
|
||||
wrap_parameters :customer, include:
|
||||
Customer.attribute_names +
|
||||
[:billing_address, :shipping_address]
|
||||
|
||||
skip_authorization_check only: :index
|
||||
|
||||
before_action :authorize_action, only: [:show, :update, :destroy]
|
||||
@@ -88,7 +92,8 @@ module Api
|
||||
attributes = params.require(:customer).permit(
|
||||
:email, :enterprise_id,
|
||||
:code, :first_name, :last_name,
|
||||
:billing_address, shipping_address: [
|
||||
:billing_address,
|
||||
shipping_address: [
|
||||
:phone, :latitude, :longitude,
|
||||
:first_name, :last_name,
|
||||
:street_address_1, :street_address_2,
|
||||
|
||||
@@ -4,7 +4,7 @@ module ManagerInvitations
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def create_new_manager(email, enterprise)
|
||||
password = Devise.friendly_token
|
||||
password = SecureRandom.base58(64)
|
||||
new_user = Spree::User.create(email:, unconfirmed_email: email, password:)
|
||||
new_user.reset_password_token = Devise.friendly_token
|
||||
# Same time as used in Devise's lib/devise/models/recoverable.rb.
|
||||
|
||||
@@ -20,25 +20,43 @@ module OrderStockCheck
|
||||
@updated_variants = check_stock_service.update_line_items
|
||||
end
|
||||
|
||||
def check_order_cycle_expiry
|
||||
def check_order_cycle_expiry(should_empty_order: true)
|
||||
return unless current_order_cycle&.closed?
|
||||
|
||||
Alert.raise_with_record("Notice: order cycle closed during checkout completion", current_order)
|
||||
current_order.empty!
|
||||
current_order.assign_order_cycle! nil
|
||||
|
||||
flash[:info] = I18n.t('order_cycle_closed')
|
||||
respond_to do |format|
|
||||
format.cable_ready {
|
||||
render status: :see_other, cable_ready: cable_car.redirect_to(url: main_app.shop_path)
|
||||
}
|
||||
format.json { render json: { path: main_app.shop_path }, status: :see_other }
|
||||
format.html { redirect_to main_app.shop_path, status: :see_other }
|
||||
end
|
||||
handle_closed_order_cycle if should_empty_order
|
||||
|
||||
flash[:info] = build_order_cycle_message(should_empty_order)
|
||||
redirect_to_shop_page(should_empty_order)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def handle_closed_order_cycle
|
||||
current_order.empty!
|
||||
current_order.assign_order_cycle!(nil)
|
||||
end
|
||||
|
||||
def build_order_cycle_message(should_empty_order)
|
||||
# If order is not emptied, we assume user will contact support for next steps
|
||||
key = should_empty_order ? 'order_cycle_closed' : 'order_cycle_closed_next_steps'
|
||||
I18n.t(key, order_number: current_order.number)
|
||||
end
|
||||
|
||||
def redirect_to_shop_page(should_empty_order)
|
||||
# If order is not emptied, redirect to shops page because shop page empties the order by default
|
||||
redirect_url = should_empty_order ? main_app.shop_path : main_app.shops_path
|
||||
|
||||
respond_to do |format|
|
||||
format.cable_ready {
|
||||
render status: :see_other, cable_ready: cable_car.redirect_to(url: redirect_url)
|
||||
}
|
||||
format.json { render json: { path: redirect_url }, status: :see_other }
|
||||
format.html { redirect_to redirect_url, status: :see_other }
|
||||
end
|
||||
end
|
||||
|
||||
def check_stock_service
|
||||
@check_stock_service ||= Orders::CheckStockService.new(order: @order)
|
||||
end
|
||||
|
||||
@@ -8,7 +8,9 @@ module PaymentGateways
|
||||
before_action :destroy_orphaned_paypal_payments, only: :confirm
|
||||
before_action :load_checkout_order, only: [:express, :confirm]
|
||||
before_action :handle_insufficient_stock, only: [:express, :confirm]
|
||||
before_action :check_order_cycle_expiry, only: [:express, :confirm]
|
||||
before_action -> { check_order_cycle_expiry(should_empty_order: false) }, only: [
|
||||
:express, :confirm
|
||||
]
|
||||
before_action :permit_parameters!
|
||||
|
||||
after_action :reset_order_when_complete, only: :confirm
|
||||
|
||||
@@ -7,7 +7,7 @@ module PaymentGateways
|
||||
|
||||
before_action :load_checkout_order, only: :confirm
|
||||
before_action :validate_payment_intent, only: :confirm
|
||||
before_action :check_order_cycle_expiry, only: :confirm
|
||||
before_action -> { check_order_cycle_expiry(should_empty_order: false) }, only: :confirm
|
||||
|
||||
def confirm
|
||||
validate_stock
|
||||
|
||||
@@ -10,6 +10,12 @@ module Spree
|
||||
|
||||
respond_to :html
|
||||
|
||||
PAYMENT_METHODS = %w{
|
||||
Spree::PaymentMethod::Check
|
||||
Spree::Gateway::PayPalExpress
|
||||
Spree::Gateway::StripeSCA
|
||||
}.index_with(&:constantize).freeze
|
||||
|
||||
def create
|
||||
force_environment
|
||||
|
||||
@@ -89,8 +95,9 @@ module Spree
|
||||
@payment_method = PaymentMethod.find(params[:pm_id])
|
||||
end
|
||||
else
|
||||
@payment_method = params[:provider_type].constantize.new
|
||||
@payment_method = PAYMENT_METHODS.fetch(params[:provider_type], PaymentMethod).new
|
||||
end
|
||||
|
||||
render partial: 'provider_settings'
|
||||
end
|
||||
|
||||
|
||||
@@ -41,5 +41,11 @@ module Admin
|
||||
def hide_producer_column?(producer_options)
|
||||
spree_current_user.column_preferences.bulk_edit_product.empty? && producer_options.one?
|
||||
end
|
||||
|
||||
# check if the user is in the "admins" group or if it's enabled for any of
|
||||
# the enterprises the user manages
|
||||
def variant_tag_enabled?(user)
|
||||
feature?(:variant_tag, user) || feature?(:variant_tag, *user.enterprises)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -52,9 +52,9 @@ module ApplicationHelper
|
||||
|
||||
# Pass URL helper calls on to spree where applicable so that we don't need to use
|
||||
# spree.foo_path in any view rendered from non-spree-namespaced controllers.
|
||||
def method_missing(method, *args, &)
|
||||
def method_missing(method, *, &)
|
||||
if method.to_s.end_with?('_path', '_url') && spree.respond_to?(method)
|
||||
spree.public_send(method, *args)
|
||||
spree.public_send(method, *)
|
||||
else
|
||||
super
|
||||
end
|
||||
|
||||
@@ -147,6 +147,10 @@ module Spree
|
||||
dom_id(record, 'spree')
|
||||
end
|
||||
|
||||
def inventory_enabled?(enterprises)
|
||||
!feature?(:variant_tag, *enterprises) && feature?(:inventory, *enterprises)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def attribute_name_for(field_name)
|
||||
|
||||
@@ -120,7 +120,7 @@ module Spree
|
||||
end
|
||||
|
||||
def cancel_event_link(order)
|
||||
event_label = I18n.t("cancel", scope: "actions")
|
||||
event_label = I18n.t("cancel_order", scope: "actions")
|
||||
button_link_to(event_label,
|
||||
fire_admin_order_url(order, e: "cancel"),
|
||||
method: :put, icon: "icon-cancel", form_id: "cancel_order_form")
|
||||
|
||||
@@ -29,7 +29,7 @@ class ApplicationRecord < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def url_for(*args)
|
||||
Rails.application.routes.url_helpers.url_for(*args)
|
||||
def url_for(*)
|
||||
Rails.application.routes.url_helpers.url_for(*)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,6 +5,18 @@ require "active_support/concern"
|
||||
module CalculatedAdjustments
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
CALCULATORS = %w{
|
||||
Calculator::DefaultTax
|
||||
Calculator::FlatPercentItemTotal
|
||||
Calculator::FlatPercentPerItem
|
||||
Calculator::FlatRate
|
||||
Calculator::FlexiRate
|
||||
Calculator::None
|
||||
Calculator::PerItem
|
||||
Calculator::PriceSack
|
||||
Calculator::Weight
|
||||
}.freeze
|
||||
|
||||
included do
|
||||
has_one :calculator, as: :calculable, class_name: "Spree::Calculator", dependent: :destroy
|
||||
accepts_nested_attributes_for :calculator
|
||||
@@ -32,7 +44,11 @@ module CalculatedAdjustments
|
||||
end
|
||||
|
||||
def calculator_type=(calculator_type)
|
||||
klass = calculator_type.constantize if calculator_type
|
||||
return unless calculator_type
|
||||
|
||||
return unless CALCULATORS.include?(calculator_type)
|
||||
|
||||
klass = calculator_type.constantize
|
||||
self.calculator = klass.new if klass && !calculator.is_a?(klass)
|
||||
end
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
module ProductSortByStocks
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
included do # rubocop:disable Metrics/BlockLength
|
||||
@on_hand_sql = Arel.sql("(
|
||||
SELECT COALESCE(SUM(si.count_on_hand), 0)
|
||||
FROM spree_variants v
|
||||
@@ -20,8 +20,18 @@ module ProductSortByStocks
|
||||
GROUP BY v.product_id
|
||||
)")
|
||||
|
||||
# When a product is On-Demand (backorderable = true), return the product name.
|
||||
# This allows alphabetical ordering inside the On-Demand group.
|
||||
# For non-On-Demand products, return NULL so normal on_hand sorting still applies.
|
||||
@backorderable_name_sql = Arel.sql("
|
||||
CASE
|
||||
WHEN (#{@backorderable_priority_sql}) THEN spree_products.name
|
||||
ELSE NULL
|
||||
END
|
||||
")
|
||||
|
||||
class << self
|
||||
attr_reader :on_hand_sql, :backorderable_priority_sql
|
||||
attr_reader :on_hand_sql, :backorderable_priority_sql, :backorderable_name_sql
|
||||
end
|
||||
|
||||
ransacker :on_hand do
|
||||
@@ -31,5 +41,9 @@ module ProductSortByStocks
|
||||
ransacker :backorderable_priority do
|
||||
@backorderable_priority_sql
|
||||
end
|
||||
|
||||
ransacker :backorderable_name do
|
||||
@backorderable_name_sql
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -25,11 +25,13 @@ class Customer < ApplicationRecord
|
||||
before_destroy :update_orders_and_delete_canceled_subscriptions
|
||||
|
||||
belongs_to :bill_address, class_name: "Spree::Address", optional: true
|
||||
alias_attribute :billing_address, :bill_address
|
||||
alias_method :billing_address, :bill_address
|
||||
alias_method :billing_address=, :bill_address=
|
||||
accepts_nested_attributes_for :bill_address
|
||||
|
||||
belongs_to :ship_address, class_name: "Spree::Address", optional: true
|
||||
alias_attribute :shipping_address, :ship_address
|
||||
alias_method :shipping_address, :ship_address
|
||||
alias_method :shipping_address=, :ship_address=
|
||||
accepts_nested_attributes_for :ship_address
|
||||
|
||||
validates :code, uniqueness: { scope: :enterprise_id, allow_nil: true }
|
||||
|
||||
@@ -77,6 +77,7 @@ class Enterprise < ApplicationRecord
|
||||
has_many :connected_apps, dependent: :destroy
|
||||
has_many :dfc_permissions, dependent: :destroy
|
||||
has_one :custom_tab, dependent: :destroy
|
||||
has_one :semantic_link, as: :subject, dependent: :delete
|
||||
|
||||
delegate :latitude, :longitude, :city, :state_name, to: :address
|
||||
|
||||
@@ -115,6 +116,9 @@ class Enterprise < ApplicationRecord
|
||||
validates :promo_image,
|
||||
processable_image: true,
|
||||
content_type: %r{\Aimage/(png|jpeg|gif|jpg|svg\+xml|webp)\Z}
|
||||
validates :white_label_logo,
|
||||
processable_image: true,
|
||||
content_type: %r{\Aimage/(png|jpeg|gif|jpg|svg\+xml|webp)\Z}
|
||||
validates :terms_and_conditions, content_type: {
|
||||
in: "application/pdf",
|
||||
message: I18n.t(:enterprise_terms_and_conditions_type_error),
|
||||
|
||||
@@ -143,7 +143,7 @@ module Spree
|
||||
can [:admin, :index, :read, :create, :edit, :update_positions, :destroy], ProducerProperty
|
||||
|
||||
can :new, TagRule
|
||||
can [:admin, :map_by_tag, :destroy], TagRule do |tag_rule|
|
||||
can [:admin, :map_by_tag, :destroy, :variant_tag_rules], TagRule do |tag_rule|
|
||||
user.enterprises.include? tag_rule.enterprise
|
||||
end
|
||||
|
||||
@@ -196,12 +196,15 @@ module Spree
|
||||
def add_product_management_abilities(user)
|
||||
# Enterprise User can only access products that they are a supplier for
|
||||
can [:create], Spree::Product
|
||||
# An enterperprise user can change a product if they are supplier of at least
|
||||
# one of the product's associated variants
|
||||
can [:admin, :read, :index, :update,
|
||||
:seo, :group_buy_options,
|
||||
:bulk_update, :clone, :delete,
|
||||
:destroy], Spree::Product do |product|
|
||||
OpenFoodNetwork::Permissions.new(user).managed_product_enterprises.include?(
|
||||
product.variants.first.supplier
|
||||
variant_suppliers = product.variants.map(&:supplier)
|
||||
OpenFoodNetwork::Permissions.new(user).managed_product_enterprises.intersect?(
|
||||
variant_suppliers
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
@@ -34,11 +34,11 @@ module Spree
|
||||
@provider.respond_to?(method_name, include_private) || super
|
||||
end
|
||||
|
||||
def method_missing(method, *args)
|
||||
def method_missing(method, *)
|
||||
if @provider.nil? || !@provider.respond_to?(method)
|
||||
super
|
||||
else
|
||||
provider.__send__(method, *args)
|
||||
provider.__send__(method, *)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -35,10 +35,12 @@ module Spree
|
||||
belongs_to :created_by, class_name: "Spree::User", optional: true
|
||||
|
||||
belongs_to :bill_address, class_name: 'Spree::Address', optional: true
|
||||
alias_attribute :billing_address, :bill_address
|
||||
alias_method :billing_address, :bill_address
|
||||
alias_method :billing_address=, :bill_address=
|
||||
|
||||
belongs_to :ship_address, class_name: 'Spree::Address', optional: true
|
||||
alias_attribute :shipping_address, :ship_address
|
||||
alias_method :shipping_address, :ship_address
|
||||
alias_method :shipping_address=, :ship_address=
|
||||
|
||||
has_many :state_changes, as: :stateful, dependent: :destroy
|
||||
has_many :line_items, -> {
|
||||
|
||||
@@ -31,7 +31,8 @@ module Spree
|
||||
|
||||
acts_as_paranoid
|
||||
|
||||
searchable_attributes :meta_keywords, :sku, :on_hand, :backorderable_priority
|
||||
searchable_attributes :meta_keywords, :sku, :on_hand, :backorderable_priority,
|
||||
:backorderable_name
|
||||
searchable_associations :properties, :variants
|
||||
searchable_scopes :active, :with_properties
|
||||
|
||||
|
||||
@@ -56,8 +56,8 @@ module Spree
|
||||
|
||||
# Send devise-based user emails asyncronously via ActiveJob
|
||||
# See: https://github.com/heartcombo/devise/tree/v3.5.10#activejob-integration
|
||||
def send_devise_notification(notification, *args)
|
||||
devise_mailer.public_send(notification, self, *args).deliver_later
|
||||
def send_devise_notification(notification, *)
|
||||
devise_mailer.public_send(notification, self, *).deliver_later
|
||||
end
|
||||
|
||||
def regenerate_reset_password_token
|
||||
|
||||
@@ -24,8 +24,10 @@ class Subscription < ApplicationRecord
|
||||
has_many :proxy_orders, dependent: :destroy
|
||||
has_many :orders, through: :proxy_orders
|
||||
|
||||
alias_attribute :billing_address, :bill_address
|
||||
alias_attribute :shipping_address, :ship_address
|
||||
alias_method :billing_address, :bill_address
|
||||
alias_method :billing_address=, :bill_address=
|
||||
alias_method :shipping_address, :ship_address
|
||||
alias_method :shipping_address=, :ship_address=
|
||||
|
||||
accepts_nested_attributes_for :subscription_line_items, allow_destroy: true
|
||||
accepts_nested_attributes_for :bill_address, :ship_address
|
||||
|
||||
@@ -7,6 +7,8 @@ class TagRule < ApplicationRecord
|
||||
|
||||
scope :for, ->(enterprise) { where(enterprise_id: enterprise) }
|
||||
scope :prioritised, -> { order('priority ASC') }
|
||||
scope :exclude_inventory, -> { where.not(type: "TagRule::FilterProducts") }
|
||||
scope :exclude_variant, -> { where.not(type: "TagRule::FilterVariants") }
|
||||
|
||||
def self.mapping_for(enterprises)
|
||||
self.for(enterprises).each_with_object({}) do |rule, mapping|
|
||||
@@ -20,6 +22,14 @@ class TagRule < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
def self.matching_variant_tag_rules_by_enterprises(enterprise_id, tag)
|
||||
rules = where(type: "TagRule::FilterVariants").for(enterprise_id)
|
||||
|
||||
return [] if rules.empty?
|
||||
|
||||
rules.select { |r| r.preferred_variant_tags =~ /#{tag}/ }
|
||||
end
|
||||
|
||||
# The following method must be overriden in a concrete tagRule
|
||||
def tags
|
||||
raise NotImplementedError, 'please use concrete TagRule'
|
||||
|
||||
22
app/models/tag_rule/filter_variants.rb
Normal file
22
app/models/tag_rule/filter_variants.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class TagRule
|
||||
class FilterVariants < TagRule
|
||||
preference :matched_variants_visibility, :string, default: "visible"
|
||||
preference :variant_tags, :string, default: ""
|
||||
|
||||
def tags_match?(variant)
|
||||
variant_tags = variant&.[]("tag_list") || []
|
||||
preferred_tags = preferred_variant_tags.split(",")
|
||||
variant_tags.intersect?(preferred_tags)
|
||||
end
|
||||
|
||||
def reject_matched?
|
||||
preferred_matched_variants_visibility != "visible"
|
||||
end
|
||||
|
||||
def tags
|
||||
preferred_variant_tags
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -62,7 +62,7 @@ module Api
|
||||
# medium: LOGO_MEDIUM_URL
|
||||
# }
|
||||
def attachment_urls(attachment, styles)
|
||||
return unless attachment.variable?
|
||||
return unless attachment.persisted? && attachment.variable?
|
||||
|
||||
styles.index_with do |style|
|
||||
Rails.application.routes.url_helpers.
|
||||
|
||||
@@ -9,7 +9,7 @@ module OrderCycles
|
||||
def create
|
||||
oc = @original_order_cycle.dup
|
||||
oc.name = I18n.t("models.order_cycle.cloned_order_cycle_name", order_cycle: oc.name)
|
||||
oc.orders_open_at = oc.orders_close_at = oc.mails_sent = oc.processed_at = nil
|
||||
oc.orders_open_at = oc.orders_close_at = oc.mails_sent = oc.processed_at = oc.opened_at = nil
|
||||
oc.coordinator_fee_ids = @original_order_cycle.coordinator_fee_ids
|
||||
oc.preferred_product_selection_from_coordinator_inventory_only =
|
||||
@original_order_cycle.preferred_product_selection_from_coordinator_inventory_only
|
||||
|
||||
@@ -118,13 +118,22 @@ module OrderCycles
|
||||
end
|
||||
|
||||
def variants
|
||||
options[:inventory_enabled] ? stocked_variants_and_overrides : stocked_variants
|
||||
return tag_rule_filtered_variants if options[:variant_tag_enabled]
|
||||
|
||||
return stocked_variants_and_overrides if options[:inventory_enabled]
|
||||
|
||||
stocked_variants
|
||||
end
|
||||
|
||||
def stocked_variants
|
||||
Spree::Variant.joins(:stock_items).where(query_stock)
|
||||
end
|
||||
|
||||
def tag_rule_filtered_variants
|
||||
VariantTagRulesFilterer.new(distributor:, customer:,
|
||||
variants_relation: stocked_variants).call
|
||||
end
|
||||
|
||||
def stocked_variants_and_overrides
|
||||
stocked_variants = Spree::Variant.
|
||||
joins("LEFT OUTER JOIN variant_overrides ON variant_overrides.variant_id = spree_variants.id
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
# ( despite the use of `TagRule::FilterProducts.prioritised` ). It will apply the "show rule"
|
||||
# if any
|
||||
# * When there is no default rule, the order of customer related rules doesn't matter, it will
|
||||
# apply the "hide rule" if any
|
||||
# apply the "show rule" over any hide rule
|
||||
#
|
||||
class ProductTagRulesFilterer
|
||||
def initialize(distributor, customer, variants_relation)
|
||||
|
||||
@@ -44,7 +44,7 @@ class ProductsRenderer
|
||||
|
||||
paginated_products = paginate(results)
|
||||
|
||||
if options[:inventory_enabled]
|
||||
if inventory_enabled?
|
||||
# Scope results with variant_overrides
|
||||
paginated_products.each { |product| product_scoper.scope(product) }
|
||||
end
|
||||
@@ -123,7 +123,7 @@ class ProductsRenderer
|
||||
includes(:default_price, :product).
|
||||
where(product_id: products)
|
||||
|
||||
if options[:inventory_enabled]
|
||||
if inventory_enabled?
|
||||
# Scope results with variant_overrides
|
||||
scoper = OpenFoodNetwork::ScopeVariantToHub.new(distributor)
|
||||
variants = variants.each { |v| scoper.scope(v) }
|
||||
@@ -143,4 +143,8 @@ class ProductsRenderer
|
||||
vs[v.product_id] << v
|
||||
end
|
||||
end
|
||||
|
||||
def inventory_enabled?
|
||||
options[:inventory_enabled] && !options[:variant_tag_enabled]
|
||||
end
|
||||
end
|
||||
|
||||
109
app/services/variant_tag_rules_filterer.rb
Normal file
109
app/services/variant_tag_rules_filterer.rb
Normal file
@@ -0,0 +1,109 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Takes a Spree::Variant AR object and filters results based on applicable tag rules.
|
||||
# Tag rules exists in the context of enterprise, customer, and variants.
|
||||
# Returns a Spree::Variant AR object.
|
||||
|
||||
# The filtering is somewhat not intuitive when they are conflicting rules in play:
|
||||
# * When a variant is hidden by a default rule, It will apply the "show rule" if any
|
||||
# * When there is no default rule, it will apply the "show rule" over any "hide rule"
|
||||
#
|
||||
class VariantTagRulesFilterer
|
||||
def initialize(distributor:, customer:, variants_relation: )
|
||||
@distributor = distributor
|
||||
@customer = customer
|
||||
@variants_relation = variants_relation
|
||||
end
|
||||
|
||||
def call
|
||||
return variants_relation unless distributor_rules.any?
|
||||
|
||||
filter(variants_relation)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_accessor :distributor, :customer, :variants_relation
|
||||
|
||||
def distributor_rules
|
||||
@distributor_rules ||= TagRule::FilterVariants.for(distributor).all
|
||||
end
|
||||
|
||||
def filter(variants_relation)
|
||||
return variants_relation unless variants_to_hide.any?
|
||||
|
||||
variants_relation.where(query_with_tag_rules)
|
||||
end
|
||||
|
||||
def query_with_tag_rules
|
||||
"#{variant_not_hidden_by_rule} OR #{variant_shown_by_rule}"
|
||||
end
|
||||
|
||||
def variant_not_hidden_by_rule
|
||||
return "FALSE" unless variants_to_hide.any?
|
||||
|
||||
"spree_variants.id NOT IN (#{variants_to_hide.join(',')})"
|
||||
end
|
||||
|
||||
def variant_shown_by_rule
|
||||
return "FALSE" unless variants_to_show.any?
|
||||
|
||||
"spree_variants.id IN (#{variants_to_show.join(',')})"
|
||||
end
|
||||
|
||||
def variants_to_hide
|
||||
@variants_to_hide ||= Spree::Variant.where(supplier: distributor)
|
||||
.tagged_with(default_rule_tags + hide_rule_tags, any: true)
|
||||
.pluck(:id)
|
||||
end
|
||||
|
||||
def variants_to_show
|
||||
@variants_to_show ||= Spree::Variant.where(supplier: distributor)
|
||||
.tagged_with(show_rule_tags, any: true)
|
||||
.pluck(:id)
|
||||
end
|
||||
|
||||
def default_rule_tags
|
||||
default_rules.map(&:preferred_variant_tags)
|
||||
end
|
||||
|
||||
def hide_rule_tags
|
||||
hide_rules.map(&:preferred_variant_tags)
|
||||
end
|
||||
|
||||
def show_rule_tags
|
||||
show_rules.map(&:preferred_variant_tags)
|
||||
end
|
||||
|
||||
def default_rules
|
||||
# These rules hide a variant with tag X and apply to all customers
|
||||
distributor_rules.select(&:is_default?)
|
||||
end
|
||||
|
||||
def non_default_rules
|
||||
# These rules show or hide a variant with tag X for customer with tag Y
|
||||
distributor_rules.reject(&:is_default?)
|
||||
end
|
||||
|
||||
def customer_applicable_rules
|
||||
# Rules which apply specifically to the current customer
|
||||
@customer_applicable_rules ||= non_default_rules.select{ |rule| customer_tagged?(rule) }
|
||||
end
|
||||
|
||||
def hide_rules
|
||||
@hide_rules ||= customer_applicable_rules
|
||||
.select{ |rule| rule.preferred_matched_variants_visibility == 'hidden' }
|
||||
end
|
||||
|
||||
def show_rules
|
||||
customer_applicable_rules - hide_rules
|
||||
end
|
||||
|
||||
def customer_tagged?(rule)
|
||||
customer_tag_list.include? rule.preferred_customer_tags
|
||||
end
|
||||
|
||||
def customer_tag_list
|
||||
customer&.tag_list || []
|
||||
end
|
||||
end
|
||||
@@ -44,8 +44,8 @@
|
||||
%h1#no_results{ 'ng-show' => '!RequestMonitor.loading && filteredCustomers.length == 0' }
|
||||
=t :no_customers_found
|
||||
|
||||
%save-bar{ dirty: "customers_form.$dirty", persist: "false" }
|
||||
%input.red{ type: "button", value: t(:save_changes), "ng-click": "submitAll(customers_form)" }
|
||||
%save-bar{ persist: "filteredCustomers.length > 0" }
|
||||
%input.red{ type: "button", value: t(:save_changes), "ng-click": "submitAll(customers_form)", "ng-disabled": "!hasUnsavedChanges()" }
|
||||
|
||||
%table.index#customers{ 'ng-show' => '!RequestMonitor.loading && filteredCustomers.length > 0' }
|
||||
%col.email{ width: "20%", 'ng-show' => 'columns.email.visible' }
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
= form_with url: main_app.import_admin_dfc_product_imports_path, html: { "data-controller": "checked" } do |form|
|
||||
-# This is a very inefficient way of holding a json blob. Maybe base64 encode or store as a temporary file
|
||||
= form.hidden_field :enterprise_id, value: @enterprise.id
|
||||
= form.hidden_field :catalog_json, value: @catalog_json
|
||||
= form.hidden_field :catalog_json, value: @catalog_data.to_json
|
||||
|
||||
%table
|
||||
%thead
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
: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"
|
||||
|
||||
@@ -5,15 +5,14 @@
|
||||
- # We use a high enough index increment so that the default tag rule should not overlap with the tag rules
|
||||
- # Rails will deal with non continous numbered tag_rules_attributes just fine, it saves us from having to manage the index state in javascript
|
||||
- current_rule_index = 1000
|
||||
- rules = @enterprise.tag_rules.prioritised.reject(&:is_default)
|
||||
- if rules.empty?
|
||||
- if @rules.empty?
|
||||
.no_tags
|
||||
= t('.no_tags_yet')
|
||||
|
||||
= render 'admin/enterprises/form/tag_rules/default_rules', f:, current_rule_index:
|
||||
|
||||
#customer-tag-rule
|
||||
- tag_groups(rules).each_with_index do |group, group_index|
|
||||
- tag_groups(@rules).each_with_index do |group, group_index|
|
||||
- current_group_index = group_index + 1
|
||||
= render TagRuleGroupFormComponent.new(group:, index: group_index, customer_rule_index: current_rule_index, tag_rule_types: @tag_rule_types)
|
||||
- # Same as above, We use a high enough increcment so that the previous tag rule group does not overlap with the next tag rule group
|
||||
|
||||
@@ -9,13 +9,12 @@
|
||||
= t('.by_default')
|
||||
%i.text-big.icon-question-sign{ "data-controller": "help-modal-link", "data-action": "click->help-modal-link#open", "data-help-modal-link-target-value": "tag_rule_help_modal" }
|
||||
#default-tag-rule
|
||||
- default_rules = @enterprise.tag_rules.select(&:is_default)
|
||||
- current_rule_index = 0
|
||||
- if default_rules.empty?
|
||||
- if @default_rules.empty?
|
||||
.no_rules
|
||||
= t('.no_rules_yet')
|
||||
- else
|
||||
- default_rules.each_with_index do |default_rule, index|
|
||||
- @default_rules.each_with_index do |default_rule, index|
|
||||
- current_rule_index = index + 1
|
||||
= render TagRuleFormComponent.new(rule: default_rule, index: index)
|
||||
%hr
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
%h3= t('.title')
|
||||
|
||||
= form_for [main_app, :admin, @order_cycle] do |f|
|
||||
- if feature?(:inventory, @order_cycle.coordinator)
|
||||
- if inventory_enabled?(@order_cycle.coordinator)
|
||||
.row
|
||||
.three.columns.alpha
|
||||
= f.label "enterprise_preferred_product_selection_from_coordinator_inventory_only", t('admin.order_cycles.edit.choose_products_from')
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
-# locals: (products:, pagy:, search_term:, producer_options:, producer_id:, category_options:, category_id:, tax_category_options:, available_tags:, tags:, flashes:, display_search_filter:, allowed_producers:)
|
||||
%turbo-frame#products-content{ target: "_top", refresh: "morph" }
|
||||
.spinner-overlay{ "data-controller": "loading", "data-products-target": "loading", class: "hidden" }
|
||||
.spinner-container
|
||||
@@ -17,7 +18,7 @@
|
||||
.container.results
|
||||
.sixteen.columns
|
||||
= render partial: 'sort', locals: { pagy:, search_term:, producer_id:, category_id:, tags: }
|
||||
= render partial: 'table', locals: { products:, producer_options:, category_options:, tax_category_options: }
|
||||
= render partial: 'table', locals: { products:, producer_options:, category_options:, tax_category_options: , allowed_producers: }
|
||||
- if pagy.present? && pagy.pages > 1
|
||||
= render partial: 'admin/shared/stimulus_pagination', locals: { pagy: pagy }
|
||||
- else
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
= select_tag :category_id, options_for_select(category_options, category_id),
|
||||
include_blank: t('.all_categories'), class: "fullwidth",
|
||||
data: { "controller": "tom-select", 'tom-select-placeholder-value': t('.search_for_categories')}
|
||||
-if feature?(:variant_tag, spree_current_user)
|
||||
-if variant_tag_enabled?(spree_current_user)
|
||||
.tags
|
||||
= label_tag :tags_name_in, t('.tags.label')
|
||||
- select_tag_options = { class: "fullwidth",
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
%td.col-category.align-left
|
||||
-# empty
|
||||
%td.col-tax_category.align-left
|
||||
- if feature?(:variant_tag, spree_current_user)
|
||||
- if variant_tag_enabled?(spree_current_user)
|
||||
%td.col-tags.align-left
|
||||
-# empty
|
||||
%td.col-inherits_properties.align-left
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
-# locals: (form:, product:, product_index:, producer_options:, category_options:, tax_category_options:, allowed_producers:, should_slide_in: false)
|
||||
= form.fields_for("products", product, index: product_index) do |product_form|
|
||||
%tbody.relaxed{ id: dom_id(product), data: { 'record-id': product_form.object.id,
|
||||
controller: "nested-form product",
|
||||
@@ -7,6 +8,9 @@
|
||||
= render partial: 'product_row', locals: { f: product_form, product:, product_index: }
|
||||
|
||||
- product.variants.each_with_index do |variant, variant_index|
|
||||
|
||||
-# Filter out variant a user has not permission to update, but keep variant with no supplier
|
||||
- next if variant.supplier.present? && !allowed_producers.include?(variant.supplier)
|
||||
= form.fields_for("products][#{product_index}][variants_attributes", variant, index: variant_index) do |variant_form|
|
||||
%tr.condensed{ id: dom_id(variant), 'data-controller': "variant", 'class': "nested-form-wrapper", 'data-new-record': variant.new_record? ? "true" : false }
|
||||
= render partial: 'variant_row', locals: { variant:, f: variant_form, category_options:, tax_category_options:, producer_options: }
|
||||
@@ -19,7 +23,7 @@
|
||||
%tr{ 'data-nested-form-target': "target" }
|
||||
%tr.condensed
|
||||
%td
|
||||
- colspan = feature?(:variant_tag, spree_current_user) ? 12 : 11
|
||||
- colspan = variant_tag_enabled?(spree_current_user) ? 12 : 11
|
||||
%td{ colspan: "#{colspan}" }
|
||||
%button.secondary.condensed.naked.icon-plus{ 'data-action': "nested-form#add",
|
||||
'aria-label': t('.new_variant') }
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
-# locals: (products:, producer_options:, category_options:, tax_category_options:, allowed_producers:)
|
||||
= form_with url: admin_products_bulk_update_path, method: :post, id: "products-form",
|
||||
builder: BulkFormBuilder,
|
||||
html: { data: { 'turbo-frame': "_self",
|
||||
@@ -26,13 +27,13 @@
|
||||
%col.col-producer{ style:"min-width: 6em" }= # (grow to fill)
|
||||
%col.col-category{ width:"8%" }
|
||||
%col.col-tax_category{ width:"8%" }
|
||||
- if feature?(:variant_tag, spree_current_user)
|
||||
- if variant_tag_enabled?(spree_current_user)
|
||||
%col.col-tags{ width:"8%" }
|
||||
%col.col-inherits_properties{ width:"5%" }
|
||||
%col{ width:"5%", style:"min-width: 3em"}= # Actions
|
||||
%thead
|
||||
%tr
|
||||
- colspan = feature?(:variant_tag, spree_current_user) ? 13 : 12
|
||||
- colspan = variant_tag_enabled?(spree_current_user) ? 13 : 12
|
||||
%td.form-actions-wrapper{ colspan: "#{colspan}" }
|
||||
.form-actions-wrapper2
|
||||
%fieldset.form-actions{ class: ("hidden" unless defined?(@error_counts)), 'data-bulk-form-target': "actions" }
|
||||
@@ -64,9 +65,9 @@
|
||||
%th.align-left.col-producer= t('admin.products_page.columns.producer')
|
||||
%th.align-left.col-category= t('admin.products_page.columns.category')
|
||||
%th.align-left.col-tax_category= t('admin.products_page.columns.tax_category')
|
||||
- if feature?(:variant_tag, spree_current_user)
|
||||
- if variant_tag_enabled?(spree_current_user)
|
||||
%th.align-left.col-tags= t('admin.products_page.columns.tags')
|
||||
%th.align-left.col-inherits_properties= t('admin.products_page.columns.inherits_properties')
|
||||
%th.align-right= t('admin.products_page.columns.actions')
|
||||
- products.each_with_index do |product, product_index|
|
||||
= render partial: 'product_variant_row', locals: { form:, product:, product_index:, producer_options:, category_options:, tax_category_options: }
|
||||
= render partial: 'product_variant_row', locals: { form:, product:, product_index:, producer_options:, category_options:, tax_category_options: , allowed_producers:}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
-# locals: (variant:, f:, category_options:, tax_category_options:, producer_options:)
|
||||
- method_on_demand, method_on_hand = variant.new_record? ? [:on_demand_desired, :on_hand_desired ]: [:on_demand, :on_hand]
|
||||
%td.col-image
|
||||
-# empty
|
||||
@@ -78,9 +79,9 @@
|
||||
aria_label: t('.tax_category_field_name'),
|
||||
placeholder_value: t('.search_for_tax_categories')))
|
||||
= error_message_on variant, :tax_category
|
||||
- if feature?(:variant_tag, spree_current_user)
|
||||
- if variant_tag_enabled?(spree_current_user)
|
||||
%td.col-tags.field.naked_inputs
|
||||
= render TagListInputComponent.new(name: f.field_name(:tag_list), tags: variant.tag_list, placeholder: t('.add_a_tag'), aria_label: t('admin.products_page.columns.tags'))
|
||||
= render TagListInputComponent.new(name: f.field_name(:tag_list), tags: variant.tag_list, autocomplete_url: variant_tag_rules_admin_tag_rules_path(enterprise_id: variant.supplier_id), placeholder: t('.add_a_tag'), aria_label: t('admin.products_page.columns.tags')) if feature?(:variant_tag, variant.supplier)
|
||||
%td.col-inherits_properties.align-left
|
||||
-# empty
|
||||
%td.align-right
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
-# locals: (product:, cloned_product:, product_index:, producer_options:, category_options: category, tax_category_options:, allowed_producers:)
|
||||
- unless flash[:error]
|
||||
- product_body = nil
|
||||
- form_with do |form|
|
||||
- product_body = render(partial: 'product_variant_row',
|
||||
locals: { form:,
|
||||
product: @cloned_product,
|
||||
product_index: @product_index,
|
||||
producer_options: @producer_options,
|
||||
category_options: @category_options,
|
||||
tax_category_options: @tax_category_options,
|
||||
product: cloned_product,
|
||||
product_index:,
|
||||
producer_options:,
|
||||
category_options:,
|
||||
tax_category_options:,
|
||||
allowed_producers:,
|
||||
should_slide_in: true },
|
||||
formats: :html)
|
||||
= turbo_stream.after dom_id(@product) do
|
||||
= turbo_stream.after dom_id(product) do
|
||||
= product_body
|
||||
|
||||
= turbo_stream.append "flashes" do
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
-# locals: (producer_options:, categories:, tax_category_options:, available_tags:, flash:, allowed_producers:)
|
||||
- content_for :page_title do
|
||||
= t('.header.title')
|
||||
- content_for :page_actions do
|
||||
@@ -13,11 +14,13 @@
|
||||
|
||||
#products_v3_page{ 'data-turbo': true }
|
||||
= render partial: "content", locals: { products: @products, pagy: @pagy, search_term: @search_term,
|
||||
producer_options: producers, producer_id: @producer_id,
|
||||
producer_options:, producer_id: @producer_id,
|
||||
category_options: categories, category_id: @category_id,
|
||||
tax_category_options:, available_tags:, tags: @tags,
|
||||
flashes: flash,
|
||||
display_search_filter: (@products.any? || @search_term.present? || @category_id.present?) }
|
||||
display_search_filter: (@products.any? || @search_term.present? || @category_id.present?),
|
||||
allowed_producers:}
|
||||
|
||||
- %w[product variant].each do |object_type|
|
||||
= render partial: 'delete_modal', locals: { object_type: }
|
||||
#modal-component
|
||||
|
||||
3
app/views/admin/tag_rules/variant_tag_rules.html.haml
Normal file
3
app/views/admin/tag_rules/variant_tag_rules.html.haml
Normal file
@@ -0,0 +1,3 @@
|
||||
- @formatted_tag_rules.each do |tag_rule|
|
||||
%li.suggestion-item{ role: "option", "data-autocomplete-value": tag_rule[:tag], "data-autocomplete-label": tag_rule[:tag] }
|
||||
= t("admin.products_v3.tag_rules.rules_per_tag", tag: tag_rule[:tag], count: tag_rule[:rules])
|
||||
@@ -17,7 +17,7 @@
|
||||
= render "layouts/matomo_tag"
|
||||
= language_meta_tags
|
||||
|
||||
= stylesheet_pack_tag "darkswarm", "data-turbo-track": "reload"
|
||||
= stylesheet_pack_tag "darkswarm", "data-turbo-track": "reload", media: "screen"
|
||||
= javascript_pack_tag "application", "data-turbo-track": "reload"
|
||||
|
||||
= render "layouts/shopfront_script" if @shopfront_layout
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
|
||||
%title
|
||||
= Spree::Config[:site_name]
|
||||
= stylesheet_link_tag 'mail'
|
||||
= stylesheet_link_tag 'mail', media: "screen"
|
||||
%body{:bgcolor => "#FFFFFF" }
|
||||
- unless @hide_ofn_navigation
|
||||
%table.head-wrap
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
= render "layouts/matomo_tag"
|
||||
= language_meta_tags
|
||||
|
||||
= stylesheet_pack_tag "darkswarm"
|
||||
= stylesheet_pack_tag "darkswarm", media: "screen"
|
||||
= javascript_include_tag "darkswarm/all"
|
||||
= javascript_pack_tag "application"
|
||||
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
.row
|
||||
.columns.small-12.medium-5
|
||||
- if current_order.nil? || current_order.distributor.nil? || current_order.distributor == @order.distributor
|
||||
- if current_order&.line_items.present?
|
||||
= link_to main_app.cart_path, :class => "button expand" do
|
||||
= t(:order_back_to_cart)
|
||||
- else
|
||||
.columns.small-12.medium-6
|
||||
= link_to "#{main_app.enterprise_shop_path(@order.distributor)}#/shop_panel", class: "button expand" do
|
||||
= t(:order_back_to_store)
|
||||
.columns.small-12.medium-6
|
||||
- if @order.distributor.website.present?
|
||||
= link_to_service "https://", @order.distributor.website, class: "button expand" do
|
||||
= t(:order_back_to_website)
|
||||
- if current_order.nil? || current_order.distributor.nil? || current_order.distributor == @order.distributor
|
||||
- if current_order&.line_items.present?
|
||||
= link_to main_app.cart_path, :class => "button expand" do
|
||||
= t(:order_back_to_cart)
|
||||
- else
|
||||
|
||||
.columns.small-12.medium-3
|
||||
= link_to "#{main_app.enterprise_shop_path(@order.distributor)}#/shop_panel", class: "button expand" do
|
||||
= t(:order_back_to_store)
|
||||
.columns.small-12.medium-3
|
||||
- if @order.distributor.website.present?
|
||||
= link_to_service "https://", @order.distributor.website, class: "button expand" do
|
||||
= t(:order_back_to_website)
|
||||
- else
|
||||
|
||||
- if order.changes_allowed?
|
||||
.columns.show-for-medium-up.medium-1
|
||||
.columns.small-12.medium-3
|
||||
= link_to main_app.cancel_order_path(@order), method: :put, class: "button secondary expand", "data-confirm": t('orders_confirm_cancel') do
|
||||
%i.ofn-i_009-close
|
||||
|
||||
@@ -7,6 +7,7 @@ import consumer from "../channels/consumer";
|
||||
import controller from "../controllers/application_controller";
|
||||
import CableReady from "cable_ready";
|
||||
import RailsNestedForm from "@stimulus-components/rails-nested-form/dist/stimulus-rails-nested-form.umd.js"; // the default module entry point is broken
|
||||
import { Autocomplete } from "stimulus-autocomplete";
|
||||
|
||||
const application = Application.start();
|
||||
const context = require.context("controllers", true, /_controller\.js$/);
|
||||
@@ -37,6 +38,7 @@ contextComponents.keys().forEach((path) => {
|
||||
});
|
||||
|
||||
application.register("nested-form", RailsNestedForm);
|
||||
application.register("autocomplete", Autocomplete);
|
||||
|
||||
application.consumer = consumer;
|
||||
StimulusReflex.initialize(application, { controller, isolate: true });
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Controller } from "stimulus";
|
||||
import { locationPathName } from "js/window_location_wrapper";
|
||||
|
||||
// This is meant to be used with the "modal:closing" event, ie:
|
||||
//
|
||||
@@ -13,7 +14,7 @@ export default class extends Controller {
|
||||
|
||||
redirect() {
|
||||
if (this.redirectValue) {
|
||||
window.location.pathname = "/shop";
|
||||
locationPathName("/shop");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ export default class PopoutController extends Controller {
|
||||
};
|
||||
|
||||
connect() {
|
||||
this.displayElements = Array.from(this.element.querySelectorAll('input:not([type="hidden"]'));
|
||||
this.displayElements = Array.from(this.element.querySelectorAll('input:not([type="hidden"])'));
|
||||
this.first_input = this.displayElements[0];
|
||||
|
||||
// Show when click or down-arrow on button
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#save-bar {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
z-index: 100;
|
||||
z-index: $save-bar-z-index;
|
||||
bottom: 0px;
|
||||
left: 0;
|
||||
padding: 8px 8px;
|
||||
|
||||
@@ -9,6 +9,10 @@ input,
|
||||
div {
|
||||
&.update-pending {
|
||||
border: solid 1px orange;
|
||||
|
||||
&:focus {
|
||||
border: solid 1px orange;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
.ts-dropdown {
|
||||
// Cover up the control with the input
|
||||
top: 0;
|
||||
z-index: $ts-dropdown-z-index;
|
||||
}
|
||||
|
||||
.dropdown-input-wrap::after {
|
||||
|
||||
@@ -186,3 +186,7 @@ $btn-condensed-height: 26px !default;
|
||||
//--------------------------------------------------------------
|
||||
$tos-banner-z-index: 1001;
|
||||
$flash-message-z-index: 1000;
|
||||
$tag-drop-down-z-index: 999;
|
||||
|
||||
$ts-dropdown-z-index: 101;
|
||||
$save-bar-z-index: 100;
|
||||
|
||||
9
app/webpacker/js/window_location_wrapper.js
Normal file
9
app/webpacker/js/window_location_wrapper.js
Normal file
@@ -0,0 +1,9 @@
|
||||
// Wrapper around location window.location
|
||||
//
|
||||
// It's mainly needed because we can't mock window.location in jsdom
|
||||
//
|
||||
const locationPathName = (pathName) => {
|
||||
window.location.pathname = pathName;
|
||||
};
|
||||
|
||||
export { locationPathName };
|
||||
@@ -79,9 +79,6 @@ Rails.application.configure do
|
||||
|
||||
"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",
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "flipper"
|
||||
require "flipper/adapters/active_record"
|
||||
require "open_food_network/feature_toggle"
|
||||
@@ -23,13 +25,50 @@ Flipper.register(:admins) do |actor|
|
||||
actor.respond_to?(:admin?) && actor.admin?
|
||||
end
|
||||
Flipper.register(:new_2024_07_03) do |actor|
|
||||
actor.respond_to?(:created_at?) && actor.created_at >= "2024-07-03".to_time
|
||||
actor.respond_to?(:created_at?) && actor.created_at >= Time.zone.parse("2024-07-03")
|
||||
end
|
||||
Flipper.register(:enterprise_created_before_2025_08_11) do |actor|
|
||||
# This group applies to enterprises only, so we return false if the actor is not an Enterprise
|
||||
next false unless actor.actor.instance_of? Enterprise
|
||||
|
||||
actor.respond_to?(:created_at?) && actor.created_at < "2025-08-11".to_time
|
||||
actor.respond_to?(:created_at?) && actor.created_at < Time.zone.parse("2025-08-11")
|
||||
end
|
||||
Flipper.register(:enterprise_created_after_2025_08_11) do |actor|
|
||||
# This group applies to enterprises only, so we return false if the actor is not an Enterprise
|
||||
next false unless actor.actor.instance_of? Enterprise
|
||||
|
||||
actor.respond_to?(:created_at?) && actor.created_at >= Time.zone.parse("2025-08-11")
|
||||
end
|
||||
|
||||
Flipper.register(:enterprise_with_no_inventory) do |actor|
|
||||
# This group applies to enterprises only, so we return false if the actor is not an Enterprise
|
||||
next false unless actor.actor.instance_of? Enterprise
|
||||
|
||||
# Uses 2025-08-11 as filter because variant tag did not exist before that, enterprise created
|
||||
# after never had access to the inventory
|
||||
enterprise_with_variant_override = Enterprise
|
||||
.where(id: VariantOverride.joins(:hub).select(:hub_id))
|
||||
.where(created_at: ..."2025-08-11")
|
||||
.distinct
|
||||
enterprise_with_no_variant_override = Enterprise
|
||||
.where.not(id: enterprise_with_variant_override)
|
||||
|
||||
enterprise_with_no_variant_override.exists?(actor.id)
|
||||
end
|
||||
|
||||
Flipper.register(:enterprise_with_inventory) do |actor|
|
||||
# This group applies to enterprises only, so we return false if the actor is not an Enterprise
|
||||
next false unless actor.actor.instance_of? Enterprise
|
||||
|
||||
# Uses 2025-08-11 as filter because variant tag did not exist before that, enterprise created
|
||||
# after never had access to the inventory
|
||||
enterprise_with_variant_override = Enterprise
|
||||
.where(id: VariantOverride.joins(:hub).select(:hub_id))
|
||||
.where(created_at: ..."2025-08-11")
|
||||
.distinct
|
||||
|
||||
# Entperprise with inventory and with variant tag not manually enabled.
|
||||
enterprise_with_variant_override.exists?(actor.id) && !Flipper.enabled?(:variant_tag, actor)
|
||||
end
|
||||
|
||||
Flipper::UI.configure do |config|
|
||||
@@ -53,4 +92,8 @@ Flipper::UI.configure do |config|
|
||||
end
|
||||
|
||||
# Add known feature toggles. This may fail if the database isn't setup yet.
|
||||
OpenFoodNetwork::FeatureToggle.setup! rescue ActiveRecord::StatementInvalid
|
||||
begin
|
||||
OpenFoodNetwork::FeatureToggle.setup!
|
||||
rescue ActiveRecord::StatementInvalid
|
||||
nil
|
||||
end
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# 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
|
||||
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
|
||||
|
||||
@@ -429,6 +429,7 @@ ar:
|
||||
create_and_add_another: "إنشاء وإضافة آخر"
|
||||
create: "انشاء"
|
||||
cancel: "إلغاء"
|
||||
cancel_order: "إلغاء"
|
||||
resume: "اكمل"
|
||||
save: "حفظ"
|
||||
edit: "تعديل"
|
||||
@@ -4553,6 +4554,7 @@ ar:
|
||||
order_cycle_tagged_bottom: "هي:"
|
||||
inventory_tagged_top: "جرد الانواع الموسومة"
|
||||
inventory_tagged_bottom: "هي:"
|
||||
variant_tagged_bottom: "هي:"
|
||||
visible: مرئي
|
||||
not_visible: غير مرئية
|
||||
tag_rule_group_form:
|
||||
|
||||
@@ -462,6 +462,7 @@ ca:
|
||||
create_and_add_another: "Crea i afegeix-ne una altra"
|
||||
create: "Crear"
|
||||
cancel: "Cancel·lar"
|
||||
cancel_order: "Cancel·lar"
|
||||
resume: "Continuar"
|
||||
save: "Desa"
|
||||
edit: "Editar"
|
||||
@@ -4382,6 +4383,7 @@ ca:
|
||||
order_cycle_tagged_bottom: "son:"
|
||||
inventory_tagged_top: "Variants d'inventari etiquetades"
|
||||
inventory_tagged_bottom: "son:"
|
||||
variant_tagged_bottom: "son:"
|
||||
visible: VISIBLE
|
||||
not_visible: NO VISIBLE
|
||||
tag_rule_group_form:
|
||||
|
||||
@@ -548,6 +548,7 @@ cy:
|
||||
create_and_add_another: "Creu ac Ychwanegu Un arall"
|
||||
create: "Creu"
|
||||
cancel: "Canslo"
|
||||
cancel_order: "Canslo"
|
||||
resume: "Ail-ddechrau"
|
||||
save: "Cadw"
|
||||
edit: "Golygu"
|
||||
@@ -4927,6 +4928,7 @@ cy:
|
||||
order_cycle_tagged_bottom: "yw:"
|
||||
inventory_tagged_top: "Tagiwyd amrywolion stocrestr"
|
||||
inventory_tagged_bottom: "yw:"
|
||||
variant_tagged_bottom: "yw:"
|
||||
visible: GWELEDOL
|
||||
not_visible: DDIM YN WELEDOL
|
||||
tag_rule_group_form:
|
||||
|
||||
@@ -460,6 +460,7 @@ de_CH:
|
||||
create_and_add_another: "Erstellen und weitere hinzufügen"
|
||||
create: "Neu"
|
||||
cancel: "Abbrechen"
|
||||
cancel_order: "Abbrechen"
|
||||
resume: "Fortsetzen"
|
||||
save: "Speichern"
|
||||
edit: "Bearbeiten"
|
||||
@@ -4408,6 +4409,7 @@ de_CH:
|
||||
order_cycle_tagged_bottom: "sind:"
|
||||
inventory_tagged_top: "Produktvarianten markiert mit"
|
||||
inventory_tagged_bottom: "sind:"
|
||||
variant_tagged_bottom: "sind:"
|
||||
visible: SICHTBAR
|
||||
not_visible: NICHT SICHTBAR
|
||||
tag_rule_group_form:
|
||||
|
||||
@@ -487,6 +487,7 @@ de_DE:
|
||||
create_and_add_another: "Erstellen und weitere hinzufügen"
|
||||
create: "Neu"
|
||||
cancel: "Abbrechen"
|
||||
cancel_order: "Stornieren"
|
||||
resume: "Fortsetzen"
|
||||
save: "Speichern"
|
||||
edit: "Bearbeiten"
|
||||
@@ -541,9 +542,11 @@ de_DE:
|
||||
clone: Duplizieren
|
||||
delete: Löschen
|
||||
remove: Löschen
|
||||
preview: Vorschau
|
||||
image:
|
||||
edit: Bearbeiten
|
||||
product_preview:
|
||||
product_preview: Produktvorschau
|
||||
shop_tab: Produkte
|
||||
adjustments:
|
||||
skipped_changing_canceled_order: "Eine stornierte Bestellung kann nicht geändert werden."
|
||||
@@ -661,6 +664,13 @@ de_DE:
|
||||
info_html: "Matomo ist eine Web- und Mobile Analytics-Anwendung. Sie können Matomo entweder lokal hosten oder einen in der Cloud gehosteten Dienst verwenden. Weitere Informationen finden Sie unter <a href='http://matomo.org' target='_blank'>matomo.org</a>."
|
||||
config_instructions_html: "Hier können Sie die OFN Matomo Integration konfigurieren. Die unten angegebene Matomo-URL sollte auf die Matomo-Instanz verweisen, an die die Benutzerverfolgungsinformationen gesendet werden. Wenn es leer bleibt, wird das Matomo-Benutzer-Tracking deaktiviert. Das Feld Site-ID ist nicht obligatorisch, aber nützlich, wenn Sie mehr als eine Website in einer einzelnen Matomo-Instanz verfolgen. Es kann auf der Matomo-Instanzkonsole gefunden werden."
|
||||
config_instructions_tag_manager_html: "Durch Festlegen der Matomo Tag Manager URL wird Matomo Tag Manager aktiviert. Mit diesem Tool können Sie Analyseereignisse einrichten. Die Matomo Tag Manager URL wird aus dem Abschnitt Installationscode von Matomo Tag Manager kopiert. Stellen Sie sicher, dass Sie den richtigen Container und die richtige Umgebung auswählen, da diese Optionen die URL ändern."
|
||||
connected_app_settings:
|
||||
edit:
|
||||
title: "Verknüpfte Apps"
|
||||
info_html: "Aktivierte Apps werden in den Unternehmenseinstellungen unter Verknüpfte Apps angezeigt."
|
||||
enabled_legend: "Aktivierte verknüpfte Apps"
|
||||
update:
|
||||
resource: Verknüpfte Apps
|
||||
customers:
|
||||
index:
|
||||
new_customer: "Neuer Kunde"
|
||||
@@ -758,6 +768,7 @@ de_DE:
|
||||
variants:
|
||||
infinity: "Unbegrenzt"
|
||||
to_order_tip: "Artikel, die auf Anfrage hergestellt werden, haben keinen festgelegten Lagerbestand."
|
||||
back_to_products_list: "Zurück zur Produktliste"
|
||||
editing_product: "Produkt bearbeiten"
|
||||
tabs:
|
||||
product_details: "Produktdetails"
|
||||
@@ -771,6 +782,17 @@ de_DE:
|
||||
title: Produkte verwalten
|
||||
content:
|
||||
loading: Produkte werden geladen...
|
||||
delete_modal:
|
||||
delete_product_modal:
|
||||
heading: "Produkt löschen"
|
||||
prompt: "Das Produkt wird dauerhaft aus Ihrer Liste entfernt."
|
||||
confirmation_text: "Produkt löschen"
|
||||
cancellation_text: "Produkt beibehalten"
|
||||
delete_variant_modal:
|
||||
heading: "Produktvariante löschen"
|
||||
prompt: "Die Produktvariante wird dauerhaft aus Ihrer Liste entfernt."
|
||||
confirmation_text: "Produktvariante löschen"
|
||||
cancellation_text: "Produktvariante beibehalten"
|
||||
filters:
|
||||
search_products: Nach Produkten suchen
|
||||
all_producers: Alle Produzenten
|
||||
@@ -784,6 +806,9 @@ de_DE:
|
||||
search: Suche
|
||||
sort:
|
||||
pagination:
|
||||
products_total_html:
|
||||
one: "<strong>%{total} Produkt</strong> für Ihre Suchkriterien gefunden."
|
||||
other: "<strong>%{count} Produkte</strong> für Ihre Suchkriterien gefunden. Zeige %{from} bis %{to}."
|
||||
per_page:
|
||||
show: Zeige
|
||||
per_page: "%{num} pro Seite"
|
||||
@@ -809,12 +834,24 @@ de_DE:
|
||||
new_variant: Neue Produktvariante
|
||||
bulk_update:
|
||||
success: Die Änderungen wurden gespeichert.
|
||||
delete_product:
|
||||
success: Das Produkt wurde gelöscht.
|
||||
error: Das Produkt konnte nicht gelöscht werden.
|
||||
delete_variant:
|
||||
success: Die Produktvariante wurde gelöscht.
|
||||
error: Die Produktvariante konnte nicht gelöscht werden.
|
||||
variant_row:
|
||||
none_tax_category: Nichts
|
||||
category_field_name: "Kategorie"
|
||||
tax_category_field_name: "Steuerkategorie"
|
||||
producer_field_name: "Produzent"
|
||||
add_a_tag: Stichwort hinzufügen
|
||||
clone:
|
||||
success: Das Produkt wurde dupliziert.
|
||||
tag_rules:
|
||||
rules_per_tag:
|
||||
one: "%{tag} hat 1 Regel"
|
||||
other: "%{tag} hat %{count} Regeln"
|
||||
product_import:
|
||||
title: Produkte importieren
|
||||
file_not_found: Die Datei konnte nicht gefunden oder nicht geöffnet werden.
|
||||
@@ -856,6 +893,8 @@ de_DE:
|
||||
product_categories: Produktkategorien
|
||||
tax_categories: Steuerkategorien
|
||||
shipping_categories: Lieferkategorien
|
||||
dfc_import_form:
|
||||
preview: Vorschau
|
||||
import:
|
||||
review: Überprüfung
|
||||
import: Importieren
|
||||
@@ -1191,7 +1230,7 @@ de_DE:
|
||||
default_rules:
|
||||
by_default: Standardregeln
|
||||
no_rules_yet: Es gelten noch keine Standardregeln.
|
||||
add_new_button: 'neue Standardregel +'
|
||||
add_new_button: '+ Neue Standardregel'
|
||||
no_tags_yet: Für dieses Unternehmen sind noch keine Stichwörter vorhanden.
|
||||
add_new_tag: '+ Neues Stichwort hinzufügen'
|
||||
show_hide_variants: 'Produktvarianten im Laden anzeigen?'
|
||||
@@ -1228,7 +1267,7 @@ de_DE:
|
||||
customers: Kunde
|
||||
net_value: Nettowert
|
||||
active: Aktiv?
|
||||
add_new: Neuer Gutschein
|
||||
add_new: + Neuer Gutschein
|
||||
no_voucher_yet: Noch keine Gutscheine vorhanden.
|
||||
white_label:
|
||||
legend: "OFN verbergen"
|
||||
@@ -1262,6 +1301,8 @@ de_DE:
|
||||
visible: Sichtbar?
|
||||
owner: Inhaber
|
||||
producer: Produzent
|
||||
sells_options:
|
||||
unspecified: nicht spezifiziert
|
||||
change_type_form:
|
||||
producer_profile: Profil
|
||||
connect_ofn: Stellen Sie sich und Ihre Produkte vor
|
||||
@@ -1298,8 +1339,10 @@ de_DE:
|
||||
contact_name: Kontaktname
|
||||
edit:
|
||||
editing: 'Einstellungen:'
|
||||
back_link: Zurück zur Unternehmensliste
|
||||
new:
|
||||
title: Neues Unternehmen
|
||||
back_link: Zurück zur Unternehmensliste
|
||||
welcome:
|
||||
welcome_title: Willkommen im Open Food Network!
|
||||
welcome_text: 'Erfolgreich erstellt:'
|
||||
@@ -1310,6 +1353,8 @@ de_DE:
|
||||
invite_manager:
|
||||
user_already_exists: "Der Benutzer existiert bereits. Bitte verwenden Sie die Funktion \"vorhandenen Benutzer hinzufügen\"."
|
||||
error: "Etwas ist schief gelaufen."
|
||||
tag_rules:
|
||||
confirm_delete: Möchten Sie diese Regel wirklich löschen?
|
||||
order_cycles:
|
||||
loading_flash:
|
||||
loading_order_cycles: BESTELLZYKLEN WERDEN GELADEN ...
|
||||
@@ -1488,6 +1533,8 @@ de_DE:
|
||||
has_no_payment_methods: "%{enterprise} hat keine Zahlungsarten."
|
||||
has_no_shipping_methods: "%{enterprise} hat keine Lieferoptionen."
|
||||
has_no_enterprise_fees: "%{enterprise} erhebt keine Gebühren."
|
||||
flashes:
|
||||
dismiss: Schließen
|
||||
side_menu:
|
||||
enterprise:
|
||||
primary_details: "Unternehmen"
|
||||
@@ -1524,6 +1571,8 @@ de_DE:
|
||||
email_confirmation: "E-Mail-Bestätigung steht aus. Wir haben eine E-Mail an %{email} gesendet."
|
||||
not_visible: "%{enterprise} ist nicht sichtbar und kann daher nicht auf der Karte oder in Suchen gefunden werden."
|
||||
reports:
|
||||
metadata:
|
||||
report_title: Bericht
|
||||
deprecated: "Dieser Bericht ist veraltet und wird in einer zukünftigen Version entfernt."
|
||||
hidden_field: "< verborgen >"
|
||||
unitsize: EINHEIT
|
||||
@@ -1575,7 +1624,7 @@ de_DE:
|
||||
orders_and_fulfillment:
|
||||
name: Bestellungs- & Erfüllungsberichte
|
||||
customers:
|
||||
name: Kundenberichte
|
||||
name: Kundenbericht
|
||||
products_and_inventory:
|
||||
name: Produkte und Katalog
|
||||
users_and_enterprises:
|
||||
@@ -1617,9 +1666,10 @@ de_DE:
|
||||
generate_report: "Bericht erstellen"
|
||||
on_screen: "Auf dem Bildschirm"
|
||||
spreadsheet: "Tabellenkalkulation (Excel, OpenOffice, ..)"
|
||||
display: Anzeige
|
||||
display: Darstellung
|
||||
summary_row: Zeilen mit Zwischensummen
|
||||
header_row: Kopfzeile
|
||||
metadata_rows: Kopfzeile mit Berichtdetails
|
||||
raw_data: Rohdaten
|
||||
formatted_data: Formatierte Daten
|
||||
packing:
|
||||
@@ -1631,6 +1681,9 @@ de_DE:
|
||||
les_communs_link: "Les Communs Open ID-Server"
|
||||
link_your_account: "Sie müssen Ihr Benutzerkonto zunächst mit dem von DFC (Les Communs Open ID Connect) verwendeten Autorisierungsanbieter verbinden."
|
||||
link_account_button: "Verbinden Sie Ihr Les Communs OIDC-Konto"
|
||||
note_expiry: |
|
||||
Die Tokens für den Zugriff auf verknüpfte Apps sind abgelaufen. Bitte aktualisieren Sie Ihre
|
||||
Kontoverknüpfung, damit alle Integrationen weiterhin funktionieren.
|
||||
view_account: "Ihr Benutzerkonto anzeigen:"
|
||||
subscriptions:
|
||||
index:
|
||||
@@ -1949,6 +2002,7 @@ de_DE:
|
||||
invoice_column_price_per_unit_without_taxes: "Einzelpreis (zzgl. Steuern)"
|
||||
invoice_column_tax_rate: "Steuersatz"
|
||||
invoice_tax_total: "Umsatzsteuersumme:"
|
||||
invoice_cancel_and_replace_invoice: "ersetzt Rechnung"
|
||||
tax_invoice: "RECHNUNG"
|
||||
tax_total: "davon Steuern (%{rate}):"
|
||||
invoice_shipping_category_delivery: "Lieferoptionen"
|
||||
@@ -2171,6 +2225,9 @@ de_DE:
|
||||
order_back_to_store: Zurück zum Laden
|
||||
order_back_to_cart: Zurück zum Warenkorb
|
||||
order_back_to_website: 'zur Website '
|
||||
checkout_details_title: Ihre Daten
|
||||
checkout_payment_title: Zahlungsart
|
||||
checkout_summary_title: Bestellabschluss
|
||||
bom_tip: "Verwenden Sie diese Seite, um Produktmengen über mehrere Bestellungen hinweg zu ändern. Produkte können bei Bedarf auch komplett aus Bestellungen entfernt werden."
|
||||
unsaved_changes_warning: "Sie haben nicht gespeicherte Änderungen, die beim Fortfahren verloren gehen."
|
||||
unsaved_changes_error: "Felder mit roten Rahmen enthalten Fehler."
|
||||
@@ -3102,6 +3159,7 @@ de_DE:
|
||||
order_cycles_no_permission_to_coordinate_error: "Keines Ihrer Unternehmen ist berechtigt, einen Bestellzyklus zu koordinieren."
|
||||
order_cycles_no_permission_to_create_error: "Sie sind nicht berechtigt, einen von diesem Unternehmen koordinierten Bestellzyklus zu erstellen."
|
||||
order_cycle_closed: "Der von Ihnen ausgewählte Bestellzyklus wurde gerade geschlossen. Bitte versuchen Sie es später noch einmal!"
|
||||
order_cycle_closed_next_steps: "Der von Ihnen gewählte Bestellzyklus wurde gerade geschlossen. Bitte kontaktieren Sie uns, um Ihre Bestellung mit der Bestellnummer %{order_number} abzuschließen!"
|
||||
back_to_orders_list: "Zurück zur Bestellübersicht"
|
||||
no_orders_found: "Keine Bestellungen gefunden."
|
||||
order_information: "Bestellinformationen"
|
||||
@@ -3636,7 +3694,7 @@ de_DE:
|
||||
spree:
|
||||
order_updated: "Bestellung aktualisiert"
|
||||
add_country: "Neues Land"
|
||||
add_state: "Neues Bundesland"
|
||||
add_state: "Bundesland hinzufügen"
|
||||
adjustment: "Anpassung"
|
||||
all: "Alle"
|
||||
associated_adjustment_closed: "Zugehörige Anpassung geschlossen"
|
||||
@@ -3680,6 +3738,7 @@ de_DE:
|
||||
resend: "Erneut senden"
|
||||
back_to_orders_list: "Zurück zur Bestellübersicht"
|
||||
back_to_payments_list: "Zurück zur Zahlungsliste"
|
||||
back_to_states_list: "Zurück zur Bundesländerliste"
|
||||
return_authorizations: "Retouren"
|
||||
cannot_create_returns: "Retouren können nicht erstellt werden, da für diese Bestellung keine Lieferung bestätigt wurde."
|
||||
select_stock: "Bestand auswählen"
|
||||
@@ -3769,6 +3828,7 @@ de_DE:
|
||||
tax_rate_amount_explanation: "Eingabe als Dezimalbetrag (d. h. bei Steuersatz 5 %, geben Sie 0.05 ein)."
|
||||
included_in_price: "Im Preis enthalten"
|
||||
show_rate_in_label: "Steuersatz im Namen anzeigen"
|
||||
back_to_tax_rates_list: "Zurück zur Liste der Steuersätze"
|
||||
tax_settings: "Steuereinstellungen"
|
||||
zones: "Zonen"
|
||||
new_zone: "Neue Zone"
|
||||
@@ -3781,6 +3841,7 @@ de_DE:
|
||||
iso_name: "ISO-Name"
|
||||
states_required: "Staaten/Bundesländer/Regionen erforderlich"
|
||||
editing_country: "Land bearbeiten"
|
||||
back_to_countries_list: "Zurück zur Länderliste"
|
||||
states: "Bundesländer"
|
||||
abbreviation: "Abkürzung"
|
||||
new_state: "Neues Bundesland"
|
||||
@@ -3943,6 +4004,7 @@ de_DE:
|
||||
continue: "Weiter"
|
||||
new:
|
||||
new_return_authorization: "Neue Retour"
|
||||
back_to_return_authorizations_list: "Zurück zur Retourenliste"
|
||||
continue: "Weiter"
|
||||
edit:
|
||||
receive: "erhalten"
|
||||
@@ -4027,6 +4089,9 @@ de_DE:
|
||||
line_item_adjustments: "Anpassungen der Einzelposten"
|
||||
order_adjustments: "Bestellanpassungen"
|
||||
order_total: "Bestellung insgesamt"
|
||||
invoices:
|
||||
index:
|
||||
order_has_changed: "Die Bestellung hat sich seit Erstellung der letzten Rechnung geändert. Die hier angezeigte Rechnung ist möglicherweise nicht mehr aktuell."
|
||||
overview:
|
||||
enterprises_header:
|
||||
ofn_with_tip: Unternehmen sind Produzenten und/oder Läden und sind die grundlegende Organisationseinheit innerhalb des Open Food Network.
|
||||
@@ -4035,6 +4100,7 @@ de_DE:
|
||||
has_no_payment_methods: "hat keine Zahlungsarten"
|
||||
has_no_shipping_methods: "hat keine Lieferoptionen"
|
||||
products:
|
||||
products_tip: "Die Produkte, die Sie über das Open Food Network verkaufen."
|
||||
active_products:
|
||||
zero: "Sie haben keine aktiven Produkte."
|
||||
one: "Sie haben ein aktives Produkt"
|
||||
@@ -4187,6 +4253,8 @@ de_DE:
|
||||
bulk_unit_size: Erforderliche Gesamtbestellmenge (in Gramm, Liter oder Stück)
|
||||
display_as:
|
||||
display_as: Anzeigen als
|
||||
clone:
|
||||
success: Produkt wurde dupliziert.
|
||||
reports:
|
||||
table:
|
||||
select_and_search: "Treffen Sie Ihre Auswahl und klicken Sie auf %{option}, um den Bericht zu erstellen."
|
||||
@@ -4258,8 +4326,16 @@ de_DE:
|
||||
total: "Gesamt"
|
||||
billing_address_name: "Name"
|
||||
taxons:
|
||||
back_to_list: "Zurück zur Produktkategorienliste"
|
||||
index:
|
||||
title: "Produktkategorien"
|
||||
new_taxon: 'Neue Produktkategorie'
|
||||
new:
|
||||
title: "Neue Produktkategorie"
|
||||
destroy:
|
||||
delete_taxon:
|
||||
success: "Die Produktkategorie wurde gelöscht."
|
||||
error: "Die Produktkategorie kann aufgrund zugewiesener Produkte nicht gelöscht werden."
|
||||
form:
|
||||
name: Name
|
||||
description: Beschreibung
|
||||
@@ -4568,6 +4644,7 @@ de_DE:
|
||||
order_cycle_tagged_bottom: "sind:"
|
||||
inventory_tagged_top: "Produktvarianten markiert mit"
|
||||
inventory_tagged_bottom: "sind:"
|
||||
variant_tagged_bottom: "sind:"
|
||||
visible: SICHTBAR
|
||||
not_visible: NICHT SICHTBAR
|
||||
tag_rule_group_form:
|
||||
|
||||
@@ -503,6 +503,7 @@ el:
|
||||
create_and_add_another: "Δημιουργία και Προσθήκη Νέου"
|
||||
create: "Δημιουργία"
|
||||
cancel: "Ακύρωση"
|
||||
cancel_order: "Ακύρωση"
|
||||
resume: "Συνέχεια"
|
||||
save: "Αποθήκευση"
|
||||
edit: "Επεξεργασία"
|
||||
@@ -4654,6 +4655,7 @@ el:
|
||||
order_cycle_tagged_bottom: "είναι:"
|
||||
inventory_tagged_top: "Ετικέτες παραλλαγών αποθέματος"
|
||||
inventory_tagged_bottom: "είναι:"
|
||||
variant_tagged_bottom: "είναι:"
|
||||
visible: ΟΡΑΤΟ
|
||||
not_visible: ΜΗ ΟΡΑΤΟ
|
||||
tag_rule_group_form:
|
||||
|
||||
@@ -596,6 +596,7 @@ en:
|
||||
create_and_add_another: "Create and Add Another"
|
||||
create: "Create"
|
||||
cancel: "Cancel"
|
||||
cancel_order: "Cancel"
|
||||
resume: "Resume"
|
||||
save: "Save"
|
||||
edit: "Edit"
|
||||
@@ -1026,6 +1027,10 @@ en:
|
||||
clone:
|
||||
success: Successfully cloned the product
|
||||
error: Unable to clone the product
|
||||
tag_rules:
|
||||
rules_per_tag:
|
||||
one: "%{tag} has 1 rule"
|
||||
other: "%{tag} has %{count} rules"
|
||||
product_import:
|
||||
title: Product Import
|
||||
file_not_found: File not found or could not be opened
|
||||
@@ -3500,6 +3505,7 @@ en:
|
||||
order_cycles_no_permission_to_coordinate_error: "None of your enterprises have permission to coordinate an order cycle"
|
||||
order_cycles_no_permission_to_create_error: "You don't have permission to create an order cycle coordinated by that enterprise"
|
||||
order_cycle_closed: "The order cycle you've selected has just closed. Please try again!"
|
||||
order_cycle_closed_next_steps: "The order cycle you've selected has just closed. Please contact us to complete your order #%{order_number}!"
|
||||
back_to_orders_list: "Back To Orders List"
|
||||
no_orders_found: "No Orders Found"
|
||||
order_information: "Order Information"
|
||||
@@ -5076,6 +5082,8 @@ en:
|
||||
order_cycle_tagged_bottom: "are:"
|
||||
inventory_tagged_top: "Inventory variants tagged"
|
||||
inventory_tagged_bottom: "are:"
|
||||
variant_tagged_top: "Variants tagged"
|
||||
variant_tagged_bottom: "are:"
|
||||
visible: VISIBLE
|
||||
not_visible: NOT VISIBLE
|
||||
tag_rule_group_form:
|
||||
|
||||
@@ -299,6 +299,7 @@ en_AU:
|
||||
create_and_add_another: "Create and Add Another"
|
||||
create: "Create"
|
||||
cancel: "Cancel"
|
||||
cancel_order: "Cancel"
|
||||
resume: "Resume"
|
||||
save: "Save"
|
||||
edit: "Edit"
|
||||
@@ -3841,6 +3842,7 @@ en_AU:
|
||||
order_cycle_tagged_bottom: "are:"
|
||||
inventory_tagged_top: "Inventory variants tagged"
|
||||
inventory_tagged_bottom: "are:"
|
||||
variant_tagged_bottom: "are:"
|
||||
visible: VISIBLE
|
||||
not_visible: NOT VISIBLE
|
||||
tag_rule_group_form:
|
||||
|
||||
@@ -278,6 +278,7 @@ en_BE:
|
||||
create_and_add_another: "Create and Add Another"
|
||||
create: "Create"
|
||||
cancel: "Cancel"
|
||||
cancel_order: "Cancel"
|
||||
save: "Save"
|
||||
edit: "Edit"
|
||||
update: "Update"
|
||||
@@ -3463,6 +3464,7 @@ en_BE:
|
||||
order_cycle_tagged_bottom: "are:"
|
||||
inventory_tagged_top: "Inventory variants tagged"
|
||||
inventory_tagged_bottom: "are:"
|
||||
variant_tagged_bottom: "are:"
|
||||
visible: VISIBLE
|
||||
not_visible: NOT VISIBLE
|
||||
tag_rule_group_form:
|
||||
|
||||
@@ -550,6 +550,7 @@ en_CA:
|
||||
create_and_add_another: "Create and Add Another"
|
||||
create: "Create"
|
||||
cancel: "Cancel"
|
||||
cancel_order: "Cancel"
|
||||
resume: "Resume"
|
||||
save: "Save"
|
||||
edit: "Edit"
|
||||
@@ -953,6 +954,10 @@ en_CA:
|
||||
clone:
|
||||
success: Successfully cloned the product
|
||||
error: Unable to clone the product
|
||||
tag_rules:
|
||||
rules_per_tag:
|
||||
one: "%{tag} has 1 rule"
|
||||
other: "%{tag} has %{count} rules"
|
||||
product_import:
|
||||
title: Product Import
|
||||
file_not_found: File not found or could not be opened
|
||||
@@ -3356,6 +3361,7 @@ en_CA:
|
||||
order_cycles_no_permission_to_coordinate_error: "None of your enterprises have permission to coordinate an order cycle"
|
||||
order_cycles_no_permission_to_create_error: "You don't have permission to create an order cycle coordinated by that enterprise"
|
||||
order_cycle_closed: "The order cycle you've selected has just closed. Please try again!"
|
||||
order_cycle_closed_next_steps: "The order cycle you've selected has just closed. Please contact us to complete your order #%{order_number}!"
|
||||
back_to_orders_list: "Back to Orders List"
|
||||
no_orders_found: "No Orders Found"
|
||||
order_information: "Order Information"
|
||||
@@ -4898,6 +4904,8 @@ en_CA:
|
||||
order_cycle_tagged_bottom: "are:"
|
||||
inventory_tagged_top: "Inventory variants tagged"
|
||||
inventory_tagged_bottom: "are:"
|
||||
variant_tagged_top: "Variants tagged"
|
||||
variant_tagged_bottom: "are:"
|
||||
visible: VISIBLE
|
||||
not_visible: NOT VISIBLE
|
||||
tag_rule_group_form:
|
||||
|
||||
@@ -283,6 +283,7 @@ en_DE:
|
||||
create_and_add_another: "Create and Add Another"
|
||||
create: "Create"
|
||||
cancel: "Cancel"
|
||||
cancel_order: "Cancel"
|
||||
save: "Save"
|
||||
edit: "Edit"
|
||||
update: "Update"
|
||||
@@ -3478,6 +3479,7 @@ en_DE:
|
||||
order_cycle_tagged_bottom: "are:"
|
||||
inventory_tagged_top: "Inventory variants tagged"
|
||||
inventory_tagged_bottom: "are:"
|
||||
variant_tagged_bottom: "are:"
|
||||
visible: VISIBLE
|
||||
not_visible: NOT VISIBLE
|
||||
tag_rule_group_form:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user