mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-11 03:40:20 +00:00
Compare commits
141 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b455755bfc | ||
|
|
619ecf9432 | ||
|
|
4f152a9151 | ||
|
|
8d7252f078 | ||
|
|
08399e753d | ||
|
|
8d721ccac8 | ||
|
|
b7a1b39c1a | ||
|
|
e276fb0386 | ||
|
|
f86eb3fb82 | ||
|
|
0d46a3bc2e | ||
|
|
0418163ad7 | ||
|
|
2e67899bcc | ||
|
|
e2536ffe71 | ||
|
|
2c6b758f66 | ||
|
|
fb0f379c43 | ||
|
|
7a4aa9dcb1 | ||
|
|
4e8d37b0b5 | ||
|
|
616de3a9c0 | ||
|
|
16b3da66c2 | ||
|
|
691995eeaa | ||
|
|
045482e07d | ||
|
|
62f25d4d31 | ||
|
|
618c7028e2 | ||
|
|
13cec27f6b | ||
|
|
5b925517f0 | ||
|
|
167099badf | ||
|
|
40d8839bc4 | ||
|
|
da1e1a9859 | ||
|
|
43ad7654b6 | ||
|
|
15d83724ea | ||
|
|
47652e9d25 | ||
|
|
b5315c2123 | ||
|
|
97ce4eaccd | ||
|
|
8814427677 | ||
|
|
4b69e192ec | ||
|
|
9c99f4868c | ||
|
|
39d59c3a5f | ||
|
|
ad9a12da0e | ||
|
|
9968776726 | ||
|
|
d99a88817d | ||
|
|
1b36cce816 | ||
|
|
4b157abd4d | ||
|
|
dc494bb0f9 | ||
|
|
b3e7b12b86 | ||
|
|
b69e6827cc | ||
|
|
340f459912 | ||
|
|
33a96d5a0f | ||
|
|
93d6db9d44 | ||
|
|
c1068af0ba | ||
|
|
482c2a4a6e | ||
|
|
2557a4de39 | ||
|
|
ab1f43f1ac | ||
|
|
f921524588 | ||
|
|
5cbd507c1e | ||
|
|
532bfaaa2d | ||
|
|
70b31a4212 | ||
|
|
9da3b0ea01 | ||
|
|
51df612c51 | ||
|
|
3be0cca230 | ||
|
|
283d13eb35 | ||
|
|
b21224d5ff | ||
|
|
4744d7b741 | ||
|
|
ac1dd74e23 | ||
|
|
970f486ec0 | ||
|
|
8c244e8b56 | ||
|
|
c3cc01c677 | ||
|
|
c63e60d782 | ||
|
|
11e8c9456d | ||
|
|
860a21f86f | ||
|
|
d24af18ff4 | ||
|
|
33b191f439 | ||
|
|
a690d39864 | ||
|
|
7c0586db7b | ||
|
|
461fd00ccd | ||
|
|
d33cabd6b2 | ||
|
|
7b21a9d30f | ||
|
|
c00e7eeecf | ||
|
|
afdb044386 | ||
|
|
b98552003c | ||
|
|
38f1754738 | ||
|
|
f872201fef | ||
|
|
ad23735384 | ||
|
|
6fd78d4647 | ||
|
|
cd3a80c502 | ||
|
|
f8c88ea8c7 | ||
|
|
4ba55c4067 | ||
|
|
813249bad7 | ||
|
|
162c58ac39 | ||
|
|
02d47d0a0d | ||
|
|
e86bf441ab | ||
|
|
f9617b8156 | ||
|
|
4650e30c09 | ||
|
|
2749965e73 | ||
|
|
e87965bda0 | ||
|
|
9f2c35d407 | ||
|
|
79af9efd29 | ||
|
|
9dcb3ec748 | ||
|
|
90c23d0245 | ||
|
|
99e238d92d | ||
|
|
b731f9b9e4 | ||
|
|
da90cdd9f6 | ||
|
|
f86c925209 | ||
|
|
0040e4d454 | ||
|
|
876d37d19a | ||
|
|
36d617bceb | ||
|
|
7c0528ad83 | ||
|
|
f25d51e772 | ||
|
|
8eb9709a04 | ||
|
|
5f31baa022 | ||
|
|
c115ab7a0d | ||
|
|
f3428494fc | ||
|
|
d748972fca | ||
|
|
b9c7925008 | ||
|
|
c11b93a4dc | ||
|
|
61e0688392 | ||
|
|
5971cdc6e2 | ||
|
|
b3a1d1269a | ||
|
|
a0011bd2e9 | ||
|
|
5e57325ce2 | ||
|
|
cd956dadda | ||
|
|
e6d556c809 | ||
|
|
f35b2be228 | ||
|
|
cc9cb966b5 | ||
|
|
34f9e08824 | ||
|
|
7d5db81017 | ||
|
|
1b03528aca | ||
|
|
9a90e46b78 | ||
|
|
b58834b11f | ||
|
|
d4811648f1 | ||
|
|
77fe1fa6f9 | ||
|
|
30804da259 | ||
|
|
1e2b8bad3f | ||
|
|
88a0737916 | ||
|
|
f5823bd618 | ||
|
|
d9453979b1 | ||
|
|
2cde74b91a | ||
|
|
3fd007fa3d | ||
|
|
e3431c7954 | ||
|
|
9fa715c709 | ||
|
|
03b7c07495 | ||
|
|
a3c08ceb7c |
4
.github/dependabot.yml
vendored
4
.github/dependabot.yml
vendored
@@ -31,6 +31,8 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
|
||||
# Only specific requirements are specified in Gemfile, so don't touch it.
|
||||
versioning-strategy: lockfile-only
|
||||
@@ -39,6 +41,8 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
|
||||
# Only specific requirements are specified in package.json, so don't touch it.
|
||||
versioning-strategy: lockfile-only
|
||||
|
||||
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
@@ -46,7 +46,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup redis
|
||||
uses: supercharge/redis-github-action@1.4.0
|
||||
uses: supercharge/redis-github-action@1.8.1
|
||||
with:
|
||||
redis-version: 6
|
||||
|
||||
@@ -124,7 +124,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup redis
|
||||
uses: supercharge/redis-github-action@1.4.0
|
||||
uses: supercharge/redis-github-action@1.8.1
|
||||
with:
|
||||
redis-version: 6
|
||||
|
||||
@@ -211,7 +211,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup redis
|
||||
uses: supercharge/redis-github-action@1.4.0
|
||||
uses: supercharge/redis-github-action@1.8.1
|
||||
with:
|
||||
redis-version: 6
|
||||
|
||||
@@ -290,7 +290,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup redis
|
||||
uses: supercharge/redis-github-action@1.4.0
|
||||
uses: supercharge/redis-github-action@1.8.1
|
||||
with:
|
||||
redis-version: 6
|
||||
|
||||
|
||||
10
Gemfile
10
Gemfile
@@ -18,7 +18,7 @@ gem 'activemerchant'
|
||||
gem 'angular-rails-templates'
|
||||
gem 'ransack', '~> 4.1.0'
|
||||
gem 'responders'
|
||||
gem 'shakapacker', '7.2.3'
|
||||
gem 'shakapacker', '8.4.0'
|
||||
|
||||
# Indirect dependency but we access it directly in JS specs.
|
||||
# It turns out to be hard to upgrade but please do if you can.
|
||||
@@ -58,6 +58,7 @@ gem 'stringex', '~> 2.8.5', require: false
|
||||
|
||||
gem 'paypal-sdk-merchant', '1.117.2'
|
||||
gem 'stripe', '~> 15'
|
||||
gem "taler"
|
||||
|
||||
gem 'devise'
|
||||
gem 'devise-encryptable'
|
||||
@@ -111,7 +112,7 @@ gem "turbo_power"
|
||||
gem "turbo-rails"
|
||||
|
||||
gem 'combine_pdf'
|
||||
gem 'wicked_pdf'
|
||||
gem 'wicked_pdf', github: "openfoodfoundation/wicked_pdf", branch: "master"
|
||||
gem 'wkhtmltopdf-binary'
|
||||
|
||||
gem 'immigrant'
|
||||
@@ -126,9 +127,8 @@ gem 'angular_rails_csrf'
|
||||
|
||||
gem 'jquery-rails', '4.4.0'
|
||||
gem 'jquery-ui-rails', '~> 4.2'
|
||||
# TODO move away from sass-rails, master branch will get rid of dependency, so we can move to
|
||||
# https://github.com/sass/embedded-host-node
|
||||
gem "select2-rails", github: "openfoodfoundation/select2-rails", branch: "v349_with_thor_v1"
|
||||
gem "select2-rails", github: "openfoodfoundation/select2-rails",
|
||||
branch: "v349_with-relaxed-dependencies"
|
||||
|
||||
gem 'good_migrations'
|
||||
|
||||
|
||||
142
Gemfile.lock
142
Gemfile.lock
@@ -10,13 +10,21 @@ GIT
|
||||
|
||||
GIT
|
||||
remote: https://github.com/openfoodfoundation/select2-rails.git
|
||||
revision: fc240e85fbdf1878ff3c39d972c0cd9a312f5ed4
|
||||
branch: v349_with_thor_v1
|
||||
revision: 9693e0cc5b04938da46692d3fa83aa8934791981
|
||||
branch: v349_with-relaxed-dependencies
|
||||
specs:
|
||||
select2-rails (3.4.9)
|
||||
sass-rails
|
||||
thor (>= 0.14)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/openfoodfoundation/wicked_pdf.git
|
||||
revision: bce498de547cdf00d037fdbec29fae844d69ee8e
|
||||
branch: master
|
||||
specs:
|
||||
wicked_pdf (2.8.1)
|
||||
activesupport
|
||||
ostruct
|
||||
|
||||
GIT
|
||||
remote: https://github.com/podia/stimulus_reflex_testing.git
|
||||
revision: abac2ee34de347c589795b4d1a8e83e0baafb201
|
||||
@@ -104,7 +112,7 @@ GEM
|
||||
rails-html-sanitizer (~> 1.6)
|
||||
active_model_serializers (0.8.4)
|
||||
activemodel (>= 3.0)
|
||||
active_storage_validations (3.0.2)
|
||||
active_storage_validations (3.0.3)
|
||||
activejob (>= 6.1.4)
|
||||
activemodel (>= 6.1.4)
|
||||
activestorage (>= 6.1.4)
|
||||
@@ -202,12 +210,12 @@ GEM
|
||||
bigdecimal (3.3.1)
|
||||
bindata (2.5.1)
|
||||
bindex (0.8.1)
|
||||
bootsnap (1.19.0)
|
||||
bootsnap (1.22.0)
|
||||
msgpack (~> 1.2)
|
||||
bugsnag (6.28.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
builder (3.3.0)
|
||||
bullet (8.0.8)
|
||||
bullet (8.1.0)
|
||||
activesupport (>= 3.0.0)
|
||||
uniform_notifier (~> 1.11)
|
||||
cable_ready (5.0.6)
|
||||
@@ -234,7 +242,7 @@ GEM
|
||||
marcel (~> 1.0)
|
||||
nokogiri (~> 1.10, >= 1.10.4)
|
||||
rubyzip (>= 1.3.0, < 3)
|
||||
cgi (0.5.0)
|
||||
cgi (0.5.1)
|
||||
childprocess (5.0.0)
|
||||
choice (0.2.0)
|
||||
chronic (0.10.2)
|
||||
@@ -249,7 +257,7 @@ GEM
|
||||
combine_pdf (1.0.31)
|
||||
matrix
|
||||
ruby-rc4 (>= 0.1.5)
|
||||
concurrent-ruby (1.3.5)
|
||||
concurrent-ruby (1.3.6)
|
||||
connection_pool (2.5.5)
|
||||
cookiejar (0.3.4)
|
||||
crack (1.0.1)
|
||||
@@ -270,7 +278,7 @@ GEM
|
||||
database_cleaner-core (2.0.1)
|
||||
datafoodconsortium-connector (1.2.0)
|
||||
virtual_assembly-semantizer (~> 1.0, >= 1.0.5)
|
||||
date (3.5.0)
|
||||
date (3.5.1)
|
||||
debug (1.11.0)
|
||||
irb (~> 1.10)
|
||||
reline (>= 0.3.8)
|
||||
@@ -305,7 +313,7 @@ GEM
|
||||
eventmachine (>= 1.0.0.beta.1)
|
||||
email_validator (2.2.4)
|
||||
activemodel
|
||||
erb (6.0.0)
|
||||
erb (6.0.1)
|
||||
erubi (1.13.1)
|
||||
et-orbi (1.3.0)
|
||||
tzinfo
|
||||
@@ -318,19 +326,21 @@ GEM
|
||||
factory_bot_rails (6.2.0)
|
||||
factory_bot (~> 6.2.0)
|
||||
railties (>= 5.0.0)
|
||||
faraday (2.9.0)
|
||||
faraday-net_http (>= 2.0, < 3.2)
|
||||
faraday (2.14.1)
|
||||
faraday-net_http (>= 2.0, < 3.5)
|
||||
json
|
||||
logger
|
||||
faraday-follow_redirects (0.4.0)
|
||||
faraday (>= 1, < 3)
|
||||
faraday-net_http (3.1.1)
|
||||
net-http
|
||||
faraday-net_http (3.4.2)
|
||||
net-http (~> 0.5)
|
||||
ferrum (0.14)
|
||||
addressable (~> 2.5)
|
||||
concurrent-ruby (~> 1.1)
|
||||
webrick (~> 1.7)
|
||||
websocket-driver (>= 0.6, < 0.8)
|
||||
ffaker (2.25.0)
|
||||
ffi (1.17.2)
|
||||
ffi (1.17.3)
|
||||
flipper (1.3.6)
|
||||
concurrent-ruby (< 2)
|
||||
flipper-active_record (1.3.6)
|
||||
@@ -388,7 +398,8 @@ GEM
|
||||
sysexits (~> 1.1)
|
||||
hashdiff (1.2.1)
|
||||
hashery (2.1.2)
|
||||
hashie (5.0.0)
|
||||
hashie (5.1.0)
|
||||
logger
|
||||
highline (3.1.2)
|
||||
reline
|
||||
htmlentities (4.4.2)
|
||||
@@ -417,10 +428,11 @@ GEM
|
||||
activerecord (>= 3.0)
|
||||
invisible_captcha (2.3.0)
|
||||
rails (>= 5.2)
|
||||
io-console (0.8.1)
|
||||
io-console (0.8.2)
|
||||
ipaddress (0.8.3)
|
||||
irb (1.15.3)
|
||||
irb (1.17.0)
|
||||
pp (>= 0.6.0)
|
||||
prism (>= 1.3.0)
|
||||
rdoc (>= 4.0.0)
|
||||
reline (>= 0.4.2)
|
||||
jmespath (1.6.2)
|
||||
@@ -430,7 +442,7 @@ GEM
|
||||
thor (>= 0.14, < 2.0)
|
||||
jquery-ui-rails (4.2.1)
|
||||
railties (>= 3.2.16)
|
||||
json (2.15.2)
|
||||
json (2.18.1)
|
||||
json-canonicalization (1.0.0)
|
||||
json-jwt (1.17.0)
|
||||
activesupport (>= 4.2)
|
||||
@@ -456,7 +468,7 @@ GEM
|
||||
activesupport (>= 4.2)
|
||||
jwt (2.10.2)
|
||||
base64
|
||||
knapsack_pro (8.4.0)
|
||||
knapsack_pro (9.2.2)
|
||||
rake
|
||||
language_server-protocol (3.17.0.5)
|
||||
launchy (3.0.0)
|
||||
@@ -466,11 +478,12 @@ GEM
|
||||
launchy (>= 2.2, < 4)
|
||||
link_header (0.0.8)
|
||||
lint_roller (1.1.0)
|
||||
listen (3.9.0)
|
||||
listen (3.10.0)
|
||||
logger
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
logger (1.7.0)
|
||||
loofah (2.24.1)
|
||||
loofah (2.25.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.12.0)
|
||||
mail (2.9.0)
|
||||
@@ -493,7 +506,8 @@ GEM
|
||||
logger
|
||||
mini_mime (1.1.5)
|
||||
mini_portile2 (2.8.6)
|
||||
minitest (5.26.2)
|
||||
minitest (6.0.1)
|
||||
prism (~> 1.5)
|
||||
monetize (1.13.0)
|
||||
money (~> 6.12)
|
||||
money (6.16.0)
|
||||
@@ -502,8 +516,8 @@ GEM
|
||||
multi_json (1.17.0)
|
||||
multi_xml (0.6.0)
|
||||
mutex_m (0.3.0)
|
||||
net-http (0.7.0)
|
||||
uri
|
||||
net-http (0.9.1)
|
||||
uri (>= 0.11.1)
|
||||
net-imap (0.5.12)
|
||||
date
|
||||
net-protocol
|
||||
@@ -515,7 +529,7 @@ GEM
|
||||
net-protocol
|
||||
newrelic_rpm (9.24.0)
|
||||
nio4r (2.7.5)
|
||||
nokogiri (1.18.10)
|
||||
nokogiri (1.19.0)
|
||||
mini_portile2 (~> 2.8.2)
|
||||
racc (~> 1.4)
|
||||
nokogiri-html5-inference (0.3.0)
|
||||
@@ -532,7 +546,7 @@ GEM
|
||||
logger
|
||||
rack (>= 2.2.3)
|
||||
rack-protection
|
||||
omniauth-rails_csrf_protection (1.0.2)
|
||||
omniauth-rails_csrf_protection (2.0.1)
|
||||
actionpack (>= 4.2)
|
||||
omniauth (~> 2.0)
|
||||
omniauth_openid_connect (0.8.0)
|
||||
@@ -561,7 +575,7 @@ GEM
|
||||
parallel (1.27.0)
|
||||
paranoia (2.6.4)
|
||||
activerecord (>= 5.1, < 7.2)
|
||||
parser (3.3.10.0)
|
||||
parser (3.3.10.2)
|
||||
ast (~> 2.4.1)
|
||||
racc
|
||||
paypal-sdk-core (0.3.4)
|
||||
@@ -579,12 +593,13 @@ GEM
|
||||
pp (0.6.3)
|
||||
prettyprint
|
||||
prettyprint (0.2.0)
|
||||
prism (1.7.0)
|
||||
prism (1.9.0)
|
||||
private_address_check (0.5.0)
|
||||
pry (0.15.2)
|
||||
pry (0.16.0)
|
||||
coderay (~> 1.1)
|
||||
method_source (~> 1.0)
|
||||
psych (5.2.6)
|
||||
reline (>= 0.6.0)
|
||||
psych (5.3.1)
|
||||
date
|
||||
stringio
|
||||
public_suffix (7.0.0)
|
||||
@@ -603,7 +618,7 @@ GEM
|
||||
railties (>= 4.2)
|
||||
raabro (1.4.0)
|
||||
racc (1.8.1)
|
||||
rack (2.2.21)
|
||||
rack (2.2.22)
|
||||
rack-mini-profiler (2.3.4)
|
||||
rack (>= 1.2.0)
|
||||
rack-oauth2 (2.3.0)
|
||||
@@ -677,7 +692,7 @@ GEM
|
||||
activesupport (>= 6.1.5)
|
||||
i18n
|
||||
rb-fsevent (0.11.2)
|
||||
rb-inotify (0.10.1)
|
||||
rb-inotify (0.11.1)
|
||||
ffi (~> 1.0)
|
||||
rdf (3.3.4)
|
||||
bcp47_spec (~> 0.2)
|
||||
@@ -686,7 +701,7 @@ GEM
|
||||
logger (~> 1.5)
|
||||
ostruct (~> 0.6)
|
||||
readline (~> 0.0)
|
||||
rdoc (6.16.0)
|
||||
rdoc (7.2.0)
|
||||
erb
|
||||
psych (>= 4.0.0)
|
||||
tsort
|
||||
@@ -702,9 +717,9 @@ GEM
|
||||
io-console (~> 0.5)
|
||||
request_store (1.7.0)
|
||||
rack (>= 1.4)
|
||||
responders (3.1.1)
|
||||
actionpack (>= 5.2)
|
||||
railties (>= 5.2)
|
||||
responders (3.2.0)
|
||||
actionpack (>= 7.0)
|
||||
railties (>= 7.0)
|
||||
rexml (3.4.4)
|
||||
roadie (5.2.1)
|
||||
css_parser (~> 1.4)
|
||||
@@ -759,7 +774,7 @@ GEM
|
||||
rswag-ui (2.17.0)
|
||||
actionpack (>= 5.2, < 8.2)
|
||||
railties (>= 5.2, < 8.2)
|
||||
rubocop (1.81.7)
|
||||
rubocop (1.84.2)
|
||||
json (~> 2.3)
|
||||
language_server-protocol (~> 3.17.0.2)
|
||||
lint_roller (~> 1.1.0)
|
||||
@@ -767,25 +782,25 @@ GEM
|
||||
parser (>= 3.3.0.2)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 2.9.3, < 3.0)
|
||||
rubocop-ast (>= 1.47.1, < 2.0)
|
||||
rubocop-ast (>= 1.49.0, < 2.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 2.4.0, < 4.0)
|
||||
rubocop-ast (1.48.0)
|
||||
rubocop-ast (1.49.0)
|
||||
parser (>= 3.3.7.2)
|
||||
prism (~> 1.4)
|
||||
prism (~> 1.7)
|
||||
rubocop-capybara (2.22.1)
|
||||
lint_roller (~> 1.1)
|
||||
rubocop (~> 1.72, >= 1.72.1)
|
||||
rubocop-factory_bot (2.28.0)
|
||||
lint_roller (~> 1.1)
|
||||
rubocop (~> 1.72, >= 1.72.1)
|
||||
rubocop-rails (2.34.2)
|
||||
rubocop-rails (2.34.3)
|
||||
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.8.0)
|
||||
rubocop-rspec (3.9.0)
|
||||
lint_roller (~> 1.1)
|
||||
rubocop (~> 1.81)
|
||||
rubocop-rspec_rails (2.32.0)
|
||||
@@ -806,17 +821,10 @@ GEM
|
||||
sanitize (7.0.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.16.8)
|
||||
sass (3.4.25)
|
||||
sass-rails (5.0.8)
|
||||
railties (>= 5.2.0)
|
||||
sass (~> 3.1)
|
||||
sprockets (>= 2.8, < 4.0)
|
||||
sprockets-rails (>= 2.0, < 4.0)
|
||||
tilt (>= 1.1, < 3)
|
||||
sd_notify (0.1.1)
|
||||
securerandom (0.4.1)
|
||||
semantic_range (3.1.0)
|
||||
shakapacker (7.2.3)
|
||||
shakapacker (8.4.0)
|
||||
activesupport (>= 5.2)
|
||||
package_json
|
||||
rack-proxy (>= 0.6.1)
|
||||
@@ -824,11 +832,12 @@ GEM
|
||||
semantic_range (>= 2.3.0)
|
||||
shoulda-matchers (7.0.1)
|
||||
activesupport (>= 7.1)
|
||||
sidekiq (7.2.4)
|
||||
concurrent-ruby (< 2)
|
||||
connection_pool (>= 2.3.0)
|
||||
rack (>= 2.2.4)
|
||||
redis-client (>= 0.19.0)
|
||||
sidekiq (7.3.10)
|
||||
base64
|
||||
connection_pool (>= 2.3.0, < 3)
|
||||
logger
|
||||
rack (>= 2.2.4, < 3.3)
|
||||
redis-client (>= 0.23.0, < 1)
|
||||
sidekiq-scheduler (5.0.3)
|
||||
rufus-scheduler (~> 3.2)
|
||||
sidekiq (>= 6, < 8)
|
||||
@@ -843,7 +852,7 @@ GEM
|
||||
caxlsx (<= 4.0)
|
||||
csv
|
||||
rodf
|
||||
spring (4.4.0)
|
||||
spring (4.4.2)
|
||||
spring-commands-rspec (1.0.4)
|
||||
spring (>= 0.9.1)
|
||||
spring-commands-rubocop (0.4.0)
|
||||
@@ -876,7 +885,7 @@ GEM
|
||||
railties (>= 5.2)
|
||||
redis (>= 4.0, < 6.0)
|
||||
stringex (2.8.6)
|
||||
stringio (3.1.8)
|
||||
stringio (3.2.0)
|
||||
stripe (15.5.0)
|
||||
swd (2.0.3)
|
||||
activesupport (>= 3)
|
||||
@@ -884,13 +893,14 @@ GEM
|
||||
faraday (~> 2.0)
|
||||
faraday-follow_redirects
|
||||
sysexits (1.2.0)
|
||||
taler (0.1.0)
|
||||
temple (0.10.4)
|
||||
terminal-table (4.0.0)
|
||||
unicode-display_width (>= 1.1.1, < 4)
|
||||
thor (1.4.0)
|
||||
thor (1.5.0)
|
||||
thread-local (1.1.0)
|
||||
tilt (2.6.1)
|
||||
timeout (0.4.4)
|
||||
timeout (0.6.0)
|
||||
tsort (0.2.0)
|
||||
ttfunk (1.8.0)
|
||||
bigdecimal (~> 3.1)
|
||||
@@ -912,7 +922,7 @@ GEM
|
||||
unicode-display_width (3.2.0)
|
||||
unicode-emoji (~> 4.1)
|
||||
unicode-emoji (4.2.0)
|
||||
uniform_notifier (1.17.0)
|
||||
uniform_notifier (1.18.0)
|
||||
uri (1.1.1)
|
||||
valid_email2 (5.2.3)
|
||||
activemodel (>= 3.2)
|
||||
@@ -956,14 +966,11 @@ GEM
|
||||
websocket-extensions (0.1.5)
|
||||
whenever (1.1.0)
|
||||
chronic (>= 0.6.3)
|
||||
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.7.3)
|
||||
zeitwerk (2.7.4)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
@@ -1085,7 +1092,7 @@ DEPENDENCIES
|
||||
rubocop-rspec_rails
|
||||
sd_notify
|
||||
select2-rails!
|
||||
shakapacker (= 7.2.3)
|
||||
shakapacker (= 8.4.0)
|
||||
shoulda-matchers
|
||||
sidekiq
|
||||
sidekiq-scheduler
|
||||
@@ -1100,6 +1107,7 @@ DEPENDENCIES
|
||||
stimulus_reflex_testing!
|
||||
stringex (~> 2.8.5)
|
||||
stripe (~> 15)
|
||||
taler
|
||||
turbo-rails
|
||||
turbo_power
|
||||
undercover
|
||||
@@ -1112,7 +1120,7 @@ DEPENDENCIES
|
||||
web-console
|
||||
webmock
|
||||
whenever
|
||||
wicked_pdf
|
||||
wicked_pdf!
|
||||
wkhtmltopdf-binary
|
||||
|
||||
RUBY VERSION
|
||||
|
||||
2
Procfile
2
Procfile
@@ -1,5 +1,5 @@
|
||||
# Foreman Procfile. Start all dev server processes with: `foreman start`
|
||||
|
||||
rails: DEV_CACHING=true bundle exec rails s -p 3000
|
||||
webpack: ./bin/shakacker-dev-server
|
||||
webpack: ./bin/shakapacker-dev-server
|
||||
sidekiq: DEV_CACHING=true bundle exec sidekiq -q mailers -q default
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
@import './mail/all.scss';
|
||||
@@ -1,3 +0,0 @@
|
||||
@import '../../../webpacker/css/admin/globals/palette.scss';
|
||||
@import 'email';
|
||||
@import 'payments_list';
|
||||
@@ -1,17 +1,18 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class SearchableDropdownComponent < ViewComponent::Base
|
||||
REMOVED_SEARCH_PLUGIN = { 'tom-select-options-value': '{ "plugins": [] }' }.freeze
|
||||
MINIMUM_OPTIONS_FOR_SEARCH_FIELD = 11 # at least 11 options are required for the search field
|
||||
|
||||
def initialize(
|
||||
form:,
|
||||
name:,
|
||||
options:,
|
||||
selected_option:,
|
||||
placeholder_value:,
|
||||
form: nil,
|
||||
placeholder_value: '',
|
||||
include_blank: false,
|
||||
aria_label: '',
|
||||
multiple: false,
|
||||
remote_url: nil,
|
||||
other_attrs: {}
|
||||
)
|
||||
@f = form
|
||||
@@ -21,13 +22,15 @@ class SearchableDropdownComponent < ViewComponent::Base
|
||||
@placeholder_value = placeholder_value
|
||||
@include_blank = include_blank
|
||||
@aria_label = aria_label
|
||||
@multiple = multiple
|
||||
@remote_url = remote_url
|
||||
@other_attrs = other_attrs
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :f, :name, :options, :selected_option, :placeholder_value, :include_blank,
|
||||
:aria_label, :other_attrs
|
||||
:aria_label, :multiple, :remote_url, :other_attrs
|
||||
|
||||
def classes
|
||||
"fullwidth #{'no-input' if remove_search_plugin?}"
|
||||
@@ -36,11 +39,33 @@ class SearchableDropdownComponent < ViewComponent::Base
|
||||
def data
|
||||
{
|
||||
controller: "tom-select",
|
||||
'tom-select-placeholder-value': placeholder_value
|
||||
}.merge(remove_search_plugin? ? REMOVED_SEARCH_PLUGIN : {})
|
||||
'tom-select-placeholder-value': placeholder_value,
|
||||
'tom-select-options-value': tom_select_options_value,
|
||||
'tom-select-remote-url-value': remote_url,
|
||||
}
|
||||
end
|
||||
|
||||
def tom_select_options_value
|
||||
plugins = []
|
||||
plugins << 'virtual_scroll' if @remote_url.present?
|
||||
plugins << 'dropdown_input' unless remove_search_plugin?
|
||||
plugins << 'remove_button' if multiple
|
||||
|
||||
{
|
||||
plugins:,
|
||||
maxItems: multiple ? nil : 1,
|
||||
}
|
||||
end
|
||||
|
||||
def uses_form_builder?
|
||||
f.present?
|
||||
end
|
||||
|
||||
def remove_search_plugin?
|
||||
@remove_search_plugin ||= options.count < MINIMUM_OPTIONS_FOR_SEARCH_FIELD
|
||||
# Remove the search plugin when:
|
||||
# - the select is multiple (it already includes a search field), or
|
||||
# - there is no remote URL and the options are below the search threshold
|
||||
@remove_search_plugin ||= multiple ||
|
||||
(@remote_url.nil? && options.count < MINIMUM_OPTIONS_FOR_SEARCH_FIELD)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
= f.select name, options_for_select(options, selected_option), { include_blank: }, class: classes, data:, 'aria-label': aria_label, **other_attrs
|
||||
- if uses_form_builder?
|
||||
= f.select name, options, { selected: selected_option, include_blank:, multiple: }, class: classes, data:, 'aria-label': aria_label, **other_attrs
|
||||
- else
|
||||
= select_tag name, options_for_select(options, selected_option), include_blank:, multiple:, class: classes, data:, 'aria-label': aria_label, **other_attrs
|
||||
|
||||
@@ -4,6 +4,7 @@ module Admin
|
||||
class ReportsController < Spree::Admin::BaseController
|
||||
include ActiveStorage::SetCurrent
|
||||
include ReportsActions
|
||||
include Reports::AjaxSearch
|
||||
|
||||
helper ReportsHelper
|
||||
|
||||
|
||||
108
app/controllers/concerns/reports/ajax_search.rb
Normal file
108
app/controllers/concerns/reports/ajax_search.rb
Normal file
@@ -0,0 +1,108 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Reports
|
||||
module AjaxSearch
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def search_enterprise_fees
|
||||
report = report_class.new(spree_current_user, params, render: false)
|
||||
fee_ids = enterprise_fee_ids(report.search.result)
|
||||
query = EnterpriseFee.where(id: fee_ids)
|
||||
|
||||
render json: build_search_response(query)
|
||||
end
|
||||
|
||||
def search_enterprise_fee_owners
|
||||
report = report_class.new(spree_current_user, params, render: false)
|
||||
owner_ids = enterprise_fee_owner_ids(report.search.result)
|
||||
query = Enterprise.where(id: owner_ids)
|
||||
|
||||
render json: build_search_response(query)
|
||||
end
|
||||
|
||||
def search_distributors
|
||||
query = frontend_data.distributors
|
||||
|
||||
render json: build_search_response(query)
|
||||
end
|
||||
|
||||
def search_order_cycles
|
||||
query = frontend_data.order_cycles
|
||||
|
||||
render json: build_search_response(query)
|
||||
end
|
||||
|
||||
def search_order_customers
|
||||
query = frontend_data.order_customers
|
||||
|
||||
render json: build_search_response(query)
|
||||
end
|
||||
|
||||
def search_suppliers
|
||||
query = frontend_data.orders_suppliers
|
||||
|
||||
render json: build_search_response(query)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def build_search_response(query)
|
||||
page = (params[:page] || 1).to_i
|
||||
per_page = 30
|
||||
|
||||
filtered_query = apply_search_filter(query)
|
||||
total_count = filtered_query.size
|
||||
items = paginated_items(filtered_query, page, per_page)
|
||||
results = format_results(items)
|
||||
|
||||
{ results: results, pagination: { more: (page * per_page) < total_count } }
|
||||
end
|
||||
|
||||
def apply_search_filter(query)
|
||||
search_term = params[:q]
|
||||
return query if search_term.blank?
|
||||
|
||||
escaped_search_term = ActiveRecord::Base.sanitize_sql_like(search_term)
|
||||
pattern = "%#{escaped_search_term}%"
|
||||
|
||||
# Handle different model types
|
||||
if query.model == OrderCycle
|
||||
query.where("order_cycles.name ILIKE ?", pattern)
|
||||
elsif query.model == Customer
|
||||
query.where("customers.email ILIKE ?", pattern)
|
||||
else
|
||||
query.where("name ILIKE ?", pattern)
|
||||
end
|
||||
end
|
||||
|
||||
def paginated_items(query, page, per_page)
|
||||
if query.model == Customer
|
||||
query.order(:email).offset((page - 1) * per_page).limit(per_page).pluck(:email, :id)
|
||||
elsif query.model == OrderCycle
|
||||
query.order('order_cycles.orders_close_at DESC')
|
||||
.offset((page - 1) * per_page)
|
||||
.limit(per_page).pluck(
|
||||
:name, :id
|
||||
)
|
||||
else
|
||||
query.order(:name).offset((page - 1) * per_page).limit(per_page).pluck(:name, :id)
|
||||
end
|
||||
end
|
||||
|
||||
def format_results(items)
|
||||
items.map { |label, value| { value:, label: } }
|
||||
end
|
||||
|
||||
def frontend_data
|
||||
@frontend_data ||= Reporting::FrontendData.new(spree_current_user)
|
||||
end
|
||||
|
||||
def enterprise_fee_owner_ids(orders)
|
||||
EnterpriseFee.where(id: enterprise_fee_ids(orders)).select(:enterprise_id)
|
||||
end
|
||||
|
||||
def enterprise_fee_ids(orders)
|
||||
Spree::Adjustment.enterprise_fee.where(order_id: orders.select(:id)).select(:originator_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
16
app/controllers/payment_gateways/taler_controller.rb
Normal file
16
app/controllers/payment_gateways/taler_controller.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module PaymentGateways
|
||||
class TalerController < BaseController
|
||||
include OrderCompletion
|
||||
|
||||
# The Taler merchant backend has taken the payment.
|
||||
# Now we just need to confirm that and update our local database
|
||||
# before finalising the order.
|
||||
def confirm
|
||||
payment = Spree::Payment.find(params[:payment_id])
|
||||
@order = payment.order
|
||||
process_payment_completion!
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -14,6 +14,7 @@ module Spree
|
||||
Spree::Gateway::PayPalExpress
|
||||
Spree::Gateway::StripeSCA
|
||||
Spree::PaymentMethod::Check
|
||||
Spree::PaymentMethod::Taler
|
||||
}.freeze
|
||||
|
||||
def create
|
||||
@@ -137,7 +138,7 @@ module Spree
|
||||
|
||||
providers.delete("Spree::Gateway::StripeSCA") unless show_stripe?
|
||||
|
||||
providers.map(&:constantize)
|
||||
providers
|
||||
end
|
||||
|
||||
# Show Stripe as an option if enabled, or if the
|
||||
|
||||
@@ -95,8 +95,7 @@ module Spree
|
||||
private
|
||||
|
||||
def load_payment_source
|
||||
if @payment.payment_method.is_a?(Spree::Gateway) &&
|
||||
@payment.payment_method.payment_profiles_supported? &&
|
||||
if @payment.payment_method.is_a?(Gateway::StripeSCA) &&
|
||||
params[:card].present? &&
|
||||
(params[:card] != 'new')
|
||||
@payment.source = CreditCard.find_by(id: params[:card])
|
||||
|
||||
@@ -9,7 +9,6 @@ module Spree
|
||||
include Spree::Core::ControllerHelpers::Auth
|
||||
include Spree::Core::ControllerHelpers::Common
|
||||
include Spree::Core::ControllerHelpers::Order
|
||||
include CablecarResponses
|
||||
|
||||
helper 'spree/base'
|
||||
|
||||
@@ -24,14 +23,12 @@ module Spree
|
||||
if spree_user_signed_in?
|
||||
flash[:success] = t('devise.success.logged_in_succesfully')
|
||||
|
||||
render cable_ready: cable_car.redirect_to(
|
||||
url: return_url_or_default(after_sign_in_path_for(spree_current_user))
|
||||
)
|
||||
redirect_to return_url_or_default(after_sign_in_path_for(spree_current_user))
|
||||
else
|
||||
render status: :unauthorized, cable_ready: cable_car.inner_html(
|
||||
"#login-feedback",
|
||||
partial("layouts/alert", locals: { type: "alert", message: t('devise.failure.invalid') })
|
||||
)
|
||||
message = t('devise.failure.invalid')
|
||||
render turbo_stream: turbo_stream.update(
|
||||
'login-feedback', partial: 'layouts/alert', locals: { message:, type: 'alert' }
|
||||
), status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
@@ -60,11 +57,13 @@ module Spree
|
||||
end
|
||||
|
||||
def render_unconfirmed_response
|
||||
render status: :unprocessable_entity, cable_ready: cable_car.inner_html(
|
||||
"#login-feedback",
|
||||
partial("layouts/alert", locals: { type: "alert", message: t(:email_unconfirmed),
|
||||
unconfirmed: true, tab: "login" })
|
||||
)
|
||||
message = t(:email_unconfirmed)
|
||||
|
||||
render turbo_stream: turbo_stream.update(
|
||||
'login-feedback',
|
||||
partial: 'layouts/alert', locals: { type: "alert", message:, unconfirmed: true,
|
||||
tab: "login", email: params.dig(:spree_user, :email) }
|
||||
), status: :unprocessable_entity
|
||||
end
|
||||
|
||||
def ensure_valid_locale_persisted
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
module Spree
|
||||
class UsersController < ::BaseController
|
||||
include I18nHelper
|
||||
include CablecarResponses
|
||||
|
||||
layout 'darkswarm'
|
||||
|
||||
@@ -25,34 +24,17 @@ module Spree
|
||||
@unconfirmed_email = spree_current_user.unconfirmed_email
|
||||
end
|
||||
|
||||
# Endpoint for queries to check if a user is already registered
|
||||
def registered_email
|
||||
registered = Spree::User.find_by(email: params[:email]).present?
|
||||
|
||||
if registered
|
||||
render status: :ok, cable_ready: cable_car.
|
||||
inner_html(
|
||||
"#login-feedback",
|
||||
partial("layouts/alert",
|
||||
locals: { type: "alert", message: t('devise.failure.already_registered') })
|
||||
).
|
||||
dispatch_event(name: "login:modal:open")
|
||||
else
|
||||
head :not_found
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
@user = Spree::User.new(user_params)
|
||||
|
||||
if @user.save
|
||||
flash[:success] = t('devise.user_registrations.spree_user.signed_up_but_unconfirmed')
|
||||
render cable_ready: cable_car.redirect_to(url: main_app.root_path)
|
||||
redirect_to main_app.root_path
|
||||
else
|
||||
render status: :unprocessable_entity, cable_ready: cable_car.morph(
|
||||
"#signup-tab",
|
||||
partial("layouts/signup_tab", locals: { signup_form_user: @user })
|
||||
)
|
||||
render turbo_stream: turbo_stream.update(
|
||||
'signup-tab',
|
||||
partial: 'layouts/signup_tab', locals: { signup_form_user: @user }
|
||||
), status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
@@ -97,13 +79,10 @@ module Spree
|
||||
end
|
||||
|
||||
def render_alert_timestamp_error_message
|
||||
render cable_ready: cable_car.inner_html(
|
||||
"#signup-feedback",
|
||||
partial("layouts/alert",
|
||||
locals: {
|
||||
type: "alert",
|
||||
message: InvisibleCaptcha.timestamp_error_message
|
||||
})
|
||||
render turbo_stream: turbo_stream.update(
|
||||
'signup-feedback',
|
||||
partial: 'layouts/alert',
|
||||
locals: { type: "alert", message: InvisibleCaptcha.timestamp_error_message }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
class UserConfirmationsController < DeviseController
|
||||
# Needed for access to current_ability, so we can authorize! actions
|
||||
include Spree::Core::ControllerHelpers::Auth
|
||||
include CablecarResponses
|
||||
|
||||
# GET /resource/confirmation?confirmation_token=abcdef
|
||||
def show
|
||||
@@ -29,12 +28,12 @@ class UserConfirmationsController < DeviseController
|
||||
set_flash_message(:error, :confirmation_not_sent)
|
||||
end
|
||||
else
|
||||
render cable_ready: cable_car.inner_html(
|
||||
"##{params[:tab] || 'forgot'}-feedback",
|
||||
partial("layouts/alert",
|
||||
locals: { type: "success", message: t("devise.confirmations.send_instructions") })
|
||||
flash.now[:sucess] = t("devise.confirmations.send_instructions")
|
||||
|
||||
return render turbo_stream: turbo_stream.update(
|
||||
"#{params[:tab] || 'forgot'}-feedback",
|
||||
partial: 'shared/flashes', locals: { flashes: flash }
|
||||
)
|
||||
return
|
||||
end
|
||||
|
||||
respond_with_navigational(resource){ redirect_to login_path }
|
||||
|
||||
@@ -1,37 +1,40 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class UserPasswordsController < Spree::UserPasswordsController
|
||||
include CablecarResponses
|
||||
|
||||
layout 'darkswarm'
|
||||
|
||||
def create
|
||||
return render_unconfirmed_response if user_unconfirmed?
|
||||
|
||||
self.resource = resource_class.send_reset_password_instructions(raw_params[resource_name])
|
||||
status = :ok
|
||||
|
||||
if resource.errors.empty?
|
||||
render cable_ready: cable_car.inner_html(
|
||||
"#forgot-feedback",
|
||||
partial("layouts/alert", locals: { type: "success", message: t(:password_reset_sent) })
|
||||
)
|
||||
message, type = [t(:password_reset_sent), :success]
|
||||
else
|
||||
render status: :not_found, cable_ready: cable_car.inner_html(
|
||||
"#forgot-feedback",
|
||||
partial("layouts/alert", locals: { type: "alert", message: t(:email_not_found) })
|
||||
)
|
||||
message, type = [t(:email_not_found), :alert]
|
||||
status = :not_found
|
||||
end
|
||||
|
||||
render turbo_stream: turbo_stream.update(
|
||||
'forgot-feedback',
|
||||
partial: 'layouts/alert',
|
||||
locals: { type:, message:, tab: 'forgot',
|
||||
unconfirmed: false, email: params.dig(:spree_user, :email) }
|
||||
), status:
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def render_unconfirmed_response
|
||||
render status: :unprocessable_entity, cable_ready: cable_car.inner_html(
|
||||
"#forgot-feedback",
|
||||
partial("layouts/alert",
|
||||
locals: { type: "alert", message: t(:email_unconfirmed),
|
||||
unconfirmed: true, tab: "forgot" })
|
||||
)
|
||||
message, type, unconfirmed, tab = [t(:email_unconfirmed), :alert, true, 'forgot']
|
||||
|
||||
render turbo_stream: turbo_stream.update(
|
||||
'forgot-feedback',
|
||||
partial: 'layouts/alert',
|
||||
locals: { type:, message:, tab:,
|
||||
unconfirmed:, email: params.dig(:spree_user, :email) }
|
||||
), status: :unprocessable_entity
|
||||
end
|
||||
|
||||
def user_unconfirmed?
|
||||
|
||||
@@ -74,6 +74,21 @@ module ApplicationHelper
|
||||
|
||||
# Update "v1" to invalidate existing cache key
|
||||
def cache_key_with_locale(key, locale)
|
||||
Array.wrap(key) + ["v2", locale.to_s, I18nDigests.for_locale(locale)]
|
||||
Array.wrap(key) + ["v3", locale.to_s, I18nDigests.for_locale(locale)]
|
||||
end
|
||||
|
||||
def pdf_stylesheet_pack_tag(source)
|
||||
# With shakapacker dev server running, the wicked_pdf_stylesheet_pack_tag will produce a
|
||||
# relative path, because we don't have `config.action_controller.asset_host`. Relative path
|
||||
# can't be resolved by `wkhtmltopdf`. So we pass the wepacker dev server host and port to
|
||||
# the shakapacker helper, so it generates the correct url.
|
||||
# For more info: https://stackoverflow.com/questions/58490299/how-to-include-css-stylesheet-into-wicked-pdf/60541688#60541688
|
||||
if running_in_development?
|
||||
options = { media: "all",
|
||||
host: "#{Shakapacker.dev_server.host}:#{Shakapacker.dev_server.port}" }
|
||||
stylesheet_pack_tag(source, **options)
|
||||
else
|
||||
wicked_pdf_stylesheet_pack_tag(source)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -34,29 +34,8 @@ module ReportsHelper
|
||||
end
|
||||
end
|
||||
|
||||
def fee_name_options(orders)
|
||||
EnterpriseFee.where(id: enterprise_fee_ids(orders))
|
||||
.pluck(:name, :id)
|
||||
end
|
||||
|
||||
def fee_owner_options(orders)
|
||||
Enterprise.where(id: enterprise_fee_owner_ids(orders))
|
||||
.pluck(:name, :id)
|
||||
end
|
||||
|
||||
delegate :currency_symbol, to: :'Spree::Money'
|
||||
|
||||
def enterprise_fee_owner_ids(orders)
|
||||
EnterpriseFee.where(id: enterprise_fee_ids(orders))
|
||||
.pluck(:enterprise_id)
|
||||
end
|
||||
|
||||
def enterprise_fee_ids(orders)
|
||||
Spree::Adjustment.enterprise_fee
|
||||
.where(order_id: orders.map(&:id))
|
||||
.pluck(:originator_id)
|
||||
end
|
||||
|
||||
def datepicker_time(datetime)
|
||||
datetime = Time.zone.parse(datetime) if datetime.is_a? String
|
||||
datetime.strftime('%Y-%m-%d %H:%M')
|
||||
|
||||
18
app/helpers/spree/admin/payment_methods_helper.rb
Normal file
18
app/helpers/spree/admin/payment_methods_helper.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Spree
|
||||
module Admin
|
||||
module PaymentMethodsHelper
|
||||
def payment_method_type_name(class_name)
|
||||
scope = "spree.admin.payment_methods.providers"
|
||||
key = class_name.demodulize.downcase
|
||||
|
||||
I18n.t(key, scope:)
|
||||
end
|
||||
|
||||
def payment_method_type_options(providers)
|
||||
providers.map { |p| [payment_method_type_name(p), p] }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -95,8 +95,8 @@ class Invoice
|
||||
def display_line_item_tax_rate(item)
|
||||
all_tax_adjustments.select { |a|
|
||||
a.adjustable.type == 'Spree::LineItem' && a.adjustable.id == item.id
|
||||
}.map(&:originator).map { |tr|
|
||||
number_to_percentage(tr.amount * 100, precision: 1)
|
||||
}.map(&:originator).map(&:amount).sort.map { |amount|
|
||||
number_to_percentage(amount * 100, precision: 1)
|
||||
}.join(", ")
|
||||
end
|
||||
|
||||
|
||||
@@ -6,6 +6,11 @@ module Spree
|
||||
class Ability
|
||||
include CanCan::Ability
|
||||
|
||||
REPORTS_SEARCH_ACTIONS = [
|
||||
:search_enterprise_fees, :search_enterprise_fee_owners, :search_distributors,
|
||||
:search_suppliers, :search_order_cycles, :search_order_customers
|
||||
].freeze
|
||||
|
||||
def initialize(user)
|
||||
clear_aliased_actions
|
||||
|
||||
@@ -260,7 +265,8 @@ module Spree
|
||||
can [:admin, :index, :import], ::Admin::DfcProductImportsController
|
||||
|
||||
# Reports page
|
||||
can [:admin, :index, :show, :create], ::Admin::ReportsController
|
||||
can [:admin, :index, :show, :create, *REPORTS_SEARCH_ACTIONS],
|
||||
::Admin::ReportsController
|
||||
can [:admin, :show, :create, :customers, :orders_and_distributors, :group_buys, :payments,
|
||||
:orders_and_fulfillment, :products_and_inventory, :order_cycle_management,
|
||||
:packing, :enterprise_fee_summary, :bulk_coop, :suppliers], :report
|
||||
@@ -392,7 +398,7 @@ module Spree
|
||||
end
|
||||
|
||||
# Reports page
|
||||
can [:admin, :index, :show, :create], ::Admin::ReportsController
|
||||
can [:admin, :index, :show, :create, *REPORTS_SEARCH_ACTIONS], ::Admin::ReportsController
|
||||
can [:admin, :customers, :group_buys, :sales_tax, :payments,
|
||||
:orders_and_distributors, :orders_and_fulfillment, :products_and_inventory,
|
||||
:order_cycle_management, :xero_invoices, :enterprise_fee_summary, :bulk_coop], :report
|
||||
|
||||
@@ -5,7 +5,7 @@ module Spree
|
||||
acts_as_taggable
|
||||
include PaymentMethodDistributors
|
||||
|
||||
delegate :authorize, :purchase, :capture, :void, :credit, to: :provider
|
||||
delegate :authorize, :purchase, :capture, :void, :credit, :refund, to: :provider
|
||||
|
||||
validates :name, :type, presence: true
|
||||
|
||||
@@ -35,6 +35,10 @@ module Spree
|
||||
end
|
||||
|
||||
def method_missing(method, *)
|
||||
message = "Deprecated delegation of Gateway##{method}"
|
||||
Alert.raise(message)
|
||||
raise message if Rails.env.local?
|
||||
|
||||
if @provider.nil? || !@provider.respond_to?(method)
|
||||
super
|
||||
else
|
||||
@@ -42,10 +46,6 @@ module Spree
|
||||
end
|
||||
end
|
||||
|
||||
def payment_profiles_supported?
|
||||
false
|
||||
end
|
||||
|
||||
def method_type
|
||||
'gateway'
|
||||
end
|
||||
|
||||
@@ -35,10 +35,6 @@ module Spree
|
||||
ActiveMerchant::Billing::StripePaymentIntentsGateway
|
||||
end
|
||||
|
||||
def payment_profiles_supported?
|
||||
true
|
||||
end
|
||||
|
||||
def stripe_account_id
|
||||
StripeAccount.find_by(enterprise_id: preferred_enterprise_id)&.stripe_user_id
|
||||
end
|
||||
@@ -84,7 +80,7 @@ module Spree
|
||||
end
|
||||
|
||||
# NOTE: this method is required by Spree::Payment::Processing
|
||||
def void(payment_intent_id, _creditcard, gateway_options)
|
||||
def void(payment_intent_id, gateway_options)
|
||||
payment_intent_response = Stripe::PaymentIntent.retrieve(
|
||||
payment_intent_id, stripe_account: stripe_account_id
|
||||
)
|
||||
@@ -101,7 +97,13 @@ module Spree
|
||||
end
|
||||
|
||||
# NOTE: this method is required by Spree::Payment::Processing
|
||||
def credit(money, _creditcard, payment_intent_id, gateway_options)
|
||||
def credit(money, payment_intent_id, gateway_options)
|
||||
gateway_options[:stripe_account] = stripe_account_id
|
||||
provider.refund(money, payment_intent_id, gateway_options)
|
||||
end
|
||||
|
||||
# NOTE: this method is required by Spree::Payment::Processing
|
||||
def refund(money, payment_intent_id, gateway_options)
|
||||
gateway_options[:stripe_account] = stripe_account_id
|
||||
provider.refund(money, payment_intent_id, gateway_options)
|
||||
end
|
||||
|
||||
@@ -24,6 +24,8 @@ module Spree
|
||||
before_validation :copy_price
|
||||
before_validation :copy_tax_category
|
||||
before_validation :copy_dimensions
|
||||
before_validation :copy_product_name, on: :create
|
||||
before_validation :copy_variant_name, on: :create
|
||||
|
||||
validates :quantity, numericality: {
|
||||
only_integer: true,
|
||||
@@ -250,6 +252,18 @@ module Spree
|
||||
adjustments.enterprise_fee
|
||||
end
|
||||
|
||||
def full_variant_name
|
||||
return variant_name if variant_name.present?
|
||||
|
||||
variant.full_name
|
||||
end
|
||||
|
||||
def full_product_name
|
||||
return product_name if product_name.present?
|
||||
|
||||
variant.product.name
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def computed_weight_from_variant
|
||||
@@ -274,6 +288,18 @@ module Spree
|
||||
order.create_tax_charge!
|
||||
end
|
||||
|
||||
def copy_product_name
|
||||
return if variant.nil? || variant.product.nil?
|
||||
|
||||
self.product_name = variant.product.name
|
||||
end
|
||||
|
||||
def copy_variant_name
|
||||
return if variant.nil?
|
||||
|
||||
self.variant_name = variant.full_name
|
||||
end
|
||||
|
||||
def update_inventory_before_destroy
|
||||
# This is necessary before destroying the line item
|
||||
# so that update_inventory will restore stock to the variant
|
||||
|
||||
@@ -34,7 +34,7 @@ module Spree
|
||||
|
||||
# invalidate previously entered payments
|
||||
after_create :invalidate_old_payments
|
||||
after_save :create_payment_profile, if: :profiles_supported?
|
||||
after_save :create_payment_profile
|
||||
|
||||
# update the order totals, etc.
|
||||
after_save :ensure_correct_adjustment, :update_order
|
||||
@@ -217,18 +217,13 @@ module Spree
|
||||
errors.blank?
|
||||
end
|
||||
|
||||
def profiles_supported?
|
||||
payment_method.respond_to?(:payment_profiles_supported?) &&
|
||||
payment_method.payment_profiles_supported?
|
||||
end
|
||||
|
||||
def create_payment_profile
|
||||
return unless source.is_a?(CreditCard)
|
||||
return unless source.try(:save_requested_by_customer?)
|
||||
return unless source.number || source.gateway_payment_profile_id
|
||||
return unless source.gateway_customer_profile_id.nil?
|
||||
|
||||
payment_method.create_profile(self)
|
||||
payment_method.try(:create_profile, self)
|
||||
rescue ActiveMerchant::ConnectionError => e
|
||||
gateway_error e
|
||||
end
|
||||
|
||||
@@ -58,16 +58,7 @@ module Spree
|
||||
protect_from_connection_error do
|
||||
check_environment
|
||||
|
||||
response = if payment_method.payment_profiles_supported?
|
||||
# Gateways supporting payment profiles will need access to credit
|
||||
# card object because this stores the payment profile information
|
||||
# so supply the authorization itself as well as the credit card,
|
||||
# rather than just the authorization code
|
||||
payment_method.void(response_code, source, gateway_options)
|
||||
else
|
||||
# Standard ActiveMerchant void usage
|
||||
payment_method.void(response_code, gateway_options)
|
||||
end
|
||||
response = payment_method.void(response_code, gateway_options)
|
||||
|
||||
record_response(response)
|
||||
|
||||
@@ -86,20 +77,11 @@ module Spree
|
||||
|
||||
credit_amount = calculate_refund_amount(credit_amount)
|
||||
|
||||
response = if payment_method.payment_profiles_supported?
|
||||
payment_method.credit(
|
||||
(credit_amount * 100).round,
|
||||
source,
|
||||
response_code,
|
||||
gateway_options
|
||||
)
|
||||
else
|
||||
payment_method.credit(
|
||||
(credit_amount * 100).round,
|
||||
response_code,
|
||||
gateway_options
|
||||
)
|
||||
end
|
||||
response = payment_method.credit(
|
||||
(credit_amount * 100).round,
|
||||
response_code,
|
||||
gateway_options
|
||||
)
|
||||
|
||||
record_response(response)
|
||||
|
||||
@@ -125,20 +107,11 @@ module Spree
|
||||
|
||||
refund_amount = calculate_refund_amount(refund_amount)
|
||||
|
||||
response = if payment_method.payment_profiles_supported?
|
||||
payment_method.refund(
|
||||
(refund_amount * 100).round,
|
||||
source,
|
||||
response_code,
|
||||
gateway_options
|
||||
)
|
||||
else
|
||||
payment_method.refund(
|
||||
(refund_amount * 100).round,
|
||||
response_code,
|
||||
gateway_options
|
||||
)
|
||||
end
|
||||
response = payment_method.refund(
|
||||
(refund_amount * 100).round,
|
||||
response_code,
|
||||
gateway_options
|
||||
)
|
||||
|
||||
record_response(response)
|
||||
|
||||
@@ -183,6 +156,7 @@ module Spree
|
||||
|
||||
options.merge!({ billing_address: order.bill_address.try(:active_merchant_hash),
|
||||
shipping_address: order.ship_address.try(:active_merchant_hash) })
|
||||
options.merge!(payment: self)
|
||||
|
||||
options
|
||||
end
|
||||
|
||||
@@ -93,10 +93,6 @@ module Spree
|
||||
unscoped { find(*) }
|
||||
end
|
||||
|
||||
def payment_profiles_supported?
|
||||
false
|
||||
end
|
||||
|
||||
def source_required?
|
||||
true
|
||||
end
|
||||
@@ -113,11 +109,6 @@ module Spree
|
||||
distributors.include?(distributor)
|
||||
end
|
||||
|
||||
def self.clean_name
|
||||
scope = "spree.admin.payment_methods.providers"
|
||||
I18n.t(name.demodulize.downcase, scope:)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def distributor_validation
|
||||
|
||||
94
app/models/spree/payment_method/taler.rb
Normal file
94
app/models/spree/payment_method/taler.rb
Normal file
@@ -0,0 +1,94 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "taler"
|
||||
|
||||
module Spree
|
||||
class PaymentMethod
|
||||
# GNU Taler is a distributed, open source payment system.
|
||||
# You need a hosted Taler backend server to process payments.
|
||||
#
|
||||
# For testing, you can use the official demo backend:
|
||||
#
|
||||
# - Merchant UX: https://backend.demo.taler.net
|
||||
# - Username: sandbox
|
||||
# - Password: sandbox
|
||||
#
|
||||
# Configure this payment method for testing with:
|
||||
#
|
||||
# - backend_url: https://backend.demo.taler.net/instances/sandbox
|
||||
# - api_key: sandbox
|
||||
class Taler < PaymentMethod
|
||||
preference :backend_url, :string
|
||||
preference :api_key, :password
|
||||
|
||||
# Name of the view to display during checkout
|
||||
def method_type
|
||||
"check" # empty view
|
||||
end
|
||||
|
||||
def external_gateway?
|
||||
true
|
||||
end
|
||||
|
||||
# The backend provides this URL. It can look like this:
|
||||
# https://backend.demo.taler.net/instances/blog/orders/2026..?token=S8Y..&session_id=b0b..
|
||||
def external_payment_url(options)
|
||||
order = options.fetch(:order)
|
||||
payment = load_payment(order)
|
||||
|
||||
payment.source ||= self
|
||||
payment.response_code ||= create_taler_order(payment)
|
||||
payment.redirect_auth_url ||= fetch_order_url(payment)
|
||||
payment.save! if payment.changed?
|
||||
|
||||
payment.redirect_auth_url
|
||||
end
|
||||
|
||||
# Main method called by Spree::Payment::Processing during checkout
|
||||
# when the user is redirected back to the app.
|
||||
#
|
||||
# The payment has already been made and we need to verify the success.
|
||||
def purchase(_money, _source, gateway_options)
|
||||
payment = gateway_options[:payment]
|
||||
|
||||
return unless payment.response_code
|
||||
|
||||
taler_order = client.fetch_order(payment.response_code)
|
||||
status = taler_order["order_status"]
|
||||
success = (status == "paid")
|
||||
message = I18n.t(status, default: status, scope: "taler.order_status")
|
||||
|
||||
ActiveMerchant::Billing::Response.new(success, message)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_payment(order)
|
||||
order.payments.checkout.where(payment_method: self).last
|
||||
end
|
||||
|
||||
def create_taler_order(payment)
|
||||
# We are ignoring currency for now so that we can test with the
|
||||
# current demo backend only working with the KUDOS currency.
|
||||
taler_amount = "KUDOS:#{payment.amount}"
|
||||
urls = Rails.application.routes.url_helpers
|
||||
new_order = client.create_order(
|
||||
taler_amount,
|
||||
I18n.t("payment_method_taler.order_summary"),
|
||||
urls.payment_gateways_confirm_taler_url(payment_id: payment.id),
|
||||
)
|
||||
|
||||
new_order["order_id"]
|
||||
end
|
||||
|
||||
def fetch_order_url(payment)
|
||||
order = client.fetch_order(payment.response_code)
|
||||
order["order_status_url"]
|
||||
end
|
||||
|
||||
def client
|
||||
@client ||= ::Taler::Client.new(preferred_backend_url, preferred_api_key)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -251,7 +251,7 @@ module Spree
|
||||
transaction do
|
||||
ExchangeVariant.
|
||||
where(exchange_variants: { variant_id: variants.with_deleted.
|
||||
select(:id) }).destroy_all
|
||||
select(:id) }).destroy_all
|
||||
|
||||
yield
|
||||
end
|
||||
|
||||
@@ -35,8 +35,8 @@ module Spree
|
||||
taxons
|
||||
.pluck('spree_taxons.id, enterprises.id AS enterprise_id')
|
||||
.each_with_object({}) do |(taxon_id, enterprise_id), collection|
|
||||
collection[enterprise_id.to_i] ||= Set.new
|
||||
collection[enterprise_id.to_i] << taxon_id
|
||||
collection[enterprise_id.to_i] ||= Set.new
|
||||
collection[enterprise_id.to_i] << taxon_id
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -167,8 +167,8 @@ module Spree
|
||||
# In Rails 3, merging two scopes on the same column will consider only the last scope.
|
||||
def self.in_distributor(distributor)
|
||||
where(id: ExchangeVariant.select(:variant_id).
|
||||
joins(:exchange).
|
||||
where('exchanges.incoming = ? AND exchanges.receiver_id = ?', false, distributor))
|
||||
joins(:exchange).
|
||||
where('exchanges.incoming = ? AND exchanges.receiver_id = ?', false, distributor))
|
||||
end
|
||||
|
||||
def self.indexed
|
||||
@@ -179,11 +179,11 @@ module Spree
|
||||
# "where(id:" is necessary so that the returned relation has no includes
|
||||
# The relation without includes will not be readonly and allow updates on it
|
||||
where(spree_variants: { id: joins(:prices).
|
||||
where(deleted_at: nil).
|
||||
where('spree_prices.currency' =>
|
||||
where(deleted_at: nil).
|
||||
where('spree_prices.currency' =>
|
||||
currency || CurrentConfig.get(:currency)).
|
||||
where.not(spree_prices: { amount: nil }).
|
||||
select("spree_variants.id") })
|
||||
where.not(spree_prices: { amount: nil }).
|
||||
select("spree_variants.id") })
|
||||
end
|
||||
|
||||
def self.linked_to(semantic_id)
|
||||
|
||||
@@ -60,8 +60,8 @@ class ProductScopeQuery
|
||||
|
||||
def product_query_includes
|
||||
[
|
||||
image: { attachment_attachment: :blob },
|
||||
variants: [:default_price, :stock_items, :variant_overrides]
|
||||
{ image: { attachment_attachment: :blob },
|
||||
variants: [:default_price, :stock_items, :variant_overrides] }
|
||||
]
|
||||
end
|
||||
|
||||
|
||||
@@ -42,10 +42,10 @@ class DfcCatalogImporter
|
||||
.includes(:semantic_links).references(:semantic_links)
|
||||
.where.not(semantic_links: { semantic_id: present_ids })
|
||||
.select do |variant|
|
||||
# Variants that were in the same catalog before:
|
||||
variant.semantic_links.map(&:semantic_id).any? do |semantic_id|
|
||||
FdcUrlBuilder.new(semantic_id).catalog_url == catalog_url
|
||||
end
|
||||
# Variants that were in the same catalog before:
|
||||
variant.semantic_links.map(&:semantic_id).any? do |semantic_id|
|
||||
FdcUrlBuilder.new(semantic_id).catalog_url == catalog_url
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -51,8 +51,8 @@ class LineItemSyncer
|
||||
def destroy_obsolete_items(order)
|
||||
order.line_items.
|
||||
where(variant_id: subscription_line_items.
|
||||
select(&:marked_for_destruction?).
|
||||
map(&:variant_id)).
|
||||
select(&:marked_for_destruction?).
|
||||
map(&:variant_id)).
|
||||
destroy_all
|
||||
end
|
||||
|
||||
@@ -77,7 +77,7 @@ class LineItemSyncer
|
||||
end
|
||||
|
||||
def add_order_update_issue(order, line_item)
|
||||
issue_description = "#{line_item.product.name} - #{line_item.variant.full_name}"
|
||||
issue_description = "#{line_item.product.name} - #{line_item.full_variant_name}"
|
||||
issue_description << " - #{stock_issue_description(line_item)}" if line_item.insufficient_stock?
|
||||
order_update_issues.add(order, issue_description)
|
||||
end
|
||||
|
||||
@@ -130,12 +130,11 @@ module Orders
|
||||
|
||||
def order_cycle_fees
|
||||
return @order_cycle_fees if defined? @order_cycle_fees
|
||||
return [] unless order_cycle && distributor
|
||||
|
||||
@order_cycle_fees = begin
|
||||
fees = []
|
||||
|
||||
return fees unless order_cycle && distributor
|
||||
|
||||
order_cycle.exchanges.supplying_to(distributor).each do |exchange|
|
||||
exchange.enterprise_fees.per_item.each do |enterprise_fee|
|
||||
fee_value = FeeValue.new(fee: enterprise_fee, role: exchange.role)
|
||||
|
||||
@@ -14,12 +14,12 @@ module PermittedAttributes
|
||||
|
||||
def self.attributes
|
||||
basic_permitted_attributes + [
|
||||
group_ids: [], user_ids: [],
|
||||
shipping_method_ids: [], payment_method_ids: [],
|
||||
address_attributes: PermittedAttributes::Address.attributes,
|
||||
business_address_attributes: PermittedAttributes::BusinessAddress.attributes,
|
||||
producer_properties_attributes: [:id, :property_name, :value, :_destroy],
|
||||
custom_tab_attributes: PermittedAttributes::CustomTab.attributes,
|
||||
{ group_ids: [], user_ids: [],
|
||||
shipping_method_ids: [], payment_method_ids: [],
|
||||
address_attributes: PermittedAttributes::Address.attributes,
|
||||
business_address_attributes: PermittedAttributes::BusinessAddress.attributes,
|
||||
producer_properties_attributes: [:id, :property_name, :value, :_destroy],
|
||||
custom_tab_attributes: PermittedAttributes::CustomTab.attributes },
|
||||
]
|
||||
end
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@ module PermittedAttributes
|
||||
private
|
||||
|
||||
def attributes
|
||||
self.class.basic_attributes + [incoming_exchanges: permitted_exchange_attributes,
|
||||
outgoing_exchanges: permitted_exchange_attributes]
|
||||
self.class.basic_attributes + [{ incoming_exchanges: permitted_exchange_attributes,
|
||||
outgoing_exchanges: permitted_exchange_attributes }]
|
||||
end
|
||||
|
||||
def permitted_exchange_attributes
|
||||
|
||||
@@ -11,7 +11,7 @@ module PermittedAttributes
|
||||
[:name, :description, :type, :active,
|
||||
:environment, :display_on, :tag_list,
|
||||
:preferred_enterprise_id, :preferred_server, :preferred_login, :preferred_password,
|
||||
:calculator_type, :preferred_api_key,
|
||||
:calculator_type, :preferred_api_key, :preferred_backend_url,
|
||||
:preferred_signature, :preferred_solution, :preferred_landing_page, :preferred_logourl,
|
||||
:preferred_test_mode, :calculator_type, { distributor_ids: [] },
|
||||
{ calculator_attributes: PermittedAttributes::Calculator.attributes }]
|
||||
|
||||
@@ -26,11 +26,11 @@ module PermittedAttributes
|
||||
|
||||
def other_permitted_attributes
|
||||
[
|
||||
subscription_line_items_attributes: [
|
||||
:id, :quantity, :variant_id, :price_estimate, :_destroy
|
||||
],
|
||||
bill_address_attributes: PermittedAttributes::Address.attributes,
|
||||
ship_address_attributes: PermittedAttributes::Address.attributes
|
||||
{ subscription_line_items_attributes: [
|
||||
:id, :quantity, :variant_id, :price_estimate, :_destroy
|
||||
],
|
||||
bill_address_attributes: PermittedAttributes::Address.attributes,
|
||||
ship_address_attributes: PermittedAttributes::Address.attributes }
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%fieldset.no-border-top
|
||||
.add_producer_properties
|
||||
= image_pack_tag 'images/spinner.gif', :plugin => 'spree', :style => 'display:none;', :id => 'busy_indicator'
|
||||
= image_pack_tag 'spinner.gif', :plugin => 'spree', :style => 'display:none;', :id => 'busy_indicator'
|
||||
%table.index.sortable{"data-sortable-link" => main_app.update_positions_admin_enterprise_producer_properties_url(@enterprise)}
|
||||
%thead
|
||||
%tr
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
%td.col-sku.field.naked_inputs
|
||||
= f.text_field :sku, 'aria-label': t('admin.products_page.columns.sku')
|
||||
= error_message_on variant, :sku
|
||||
%td.col-unir_scale.field.naked_inputs{ 'data-controller': 'toggle-control', 'data-toggle-control-match-value': 'items' }
|
||||
%td.col-unit_scale.field.naked_inputs{ 'data-controller': 'toggle-control', 'data-toggle-control-match-value': 'items' }
|
||||
= f.hidden_field :variant_unit
|
||||
= f.hidden_field :variant_unit_scale
|
||||
= f.select :variant_unit_with_scale,
|
||||
|
||||
@@ -1,23 +1,50 @@
|
||||
- search_url_query = {report_type: :enterprise_fee_summary, report_subtype: :enterprise_fees_with_tax_report_by_order}
|
||||
.row
|
||||
.alpha.two.columns= label_tag nil, t(:report_hubs)
|
||||
.omega.fourteen.columns= f.collection_select(:distributor_id_in, @data.distributors, :id, :name, {}, {class: "select2 fullwidth", multiple: true})
|
||||
.omega.fourteen.columns
|
||||
= render(SearchableDropdownComponent.new(form: f,
|
||||
name: :distributor_id_in,
|
||||
options: [],
|
||||
selected_option: params.dig(:q, :distributor_id_in),
|
||||
multiple: true,
|
||||
remote_url: admin_reports_search_distributors_url))
|
||||
|
||||
.row
|
||||
.alpha.two.columns= label_tag nil, t(:report_customers_cycle)
|
||||
.omega.fourteen.columns
|
||||
= f.select(:order_cycle_id_in, report_order_cycle_options(@data.order_cycles), {selected: params.dig(:q, :order_cycle_id_in)}, {class: "select2 fullwidth", multiple: true})
|
||||
= render(SearchableDropdownComponent.new(form: f,
|
||||
name: :order_cycle_id_in,
|
||||
options: [],
|
||||
selected_option: params.dig(:q, :order_cycle_id_in),
|
||||
multiple: true,
|
||||
remote_url: admin_reports_search_order_cycles_url))
|
||||
|
||||
.row
|
||||
.alpha.two.columns= label_tag nil, t(:fee_name)
|
||||
.omega.fourteen.columns
|
||||
= f.select(:enterprise_fee_id_in, fee_name_options(@report.search.result), {selected: params.dig(:q, :enterprise_fee_id_in)}, {class: "select2 fullwidth", multiple: true})
|
||||
= render(SearchableDropdownComponent.new(form: f,
|
||||
name: :enterprise_fee_id_in,
|
||||
options: [],
|
||||
selected_option: params.dig(:q, :enterprise_fee_id_in),
|
||||
multiple: true,
|
||||
remote_url: admin_reports_search_enterprise_fees_url(search_url_query)))
|
||||
|
||||
.row
|
||||
.alpha.two.columns= label_tag nil, t(:fee_owner)
|
||||
.omega.fourteen.columns
|
||||
= f.select(:enterprise_fee_owner_id_in, fee_owner_options(@report.search.result), {selected: params.dig(:q, :enterprise_fee_owner_id_in)}, {class: "select2 fullwidth", multiple: true})
|
||||
= render(SearchableDropdownComponent.new(form: f,
|
||||
name: :enterprise_fee_owner_id_in,
|
||||
options: [],
|
||||
selected_option: params.dig(:q, :enterprise_fee_owner_id_in),
|
||||
multiple: true,
|
||||
remote_url: admin_reports_search_enterprise_fee_owners_url(search_url_query)))
|
||||
|
||||
.row
|
||||
.alpha.two.columns= label_tag nil, t(:report_customers)
|
||||
.omega.fourteen.columns
|
||||
= f.select(:customer_id_in, customer_email_options(@data.order_customers), {selected: params.dig(:q, :customer_id_in)}, {class: "select2 fullwidth", multiple: true})
|
||||
= render(SearchableDropdownComponent.new(form: f,
|
||||
name: :customer_id_in,
|
||||
options: [],
|
||||
selected_option: params.dig(:q, :customer_id_in),
|
||||
multiple: true,
|
||||
remote_url: admin_reports_search_order_customers_url))
|
||||
|
||||
@@ -1,27 +1,57 @@
|
||||
- search_url_query = {report_type: :enterprise_fee_summary, report_subtype: :enterprise_fees_with_tax_report_by_producer}
|
||||
.row
|
||||
.alpha.two.columns= label_tag nil, t(:report_hubs)
|
||||
.omega.fourteen.columns= f.collection_select(:distributor_id_in, @data.distributors, :id, :name, {}, {class: "select2 fullwidth", multiple: true})
|
||||
|
||||
.omega.fourteen.columns
|
||||
= render(SearchableDropdownComponent.new(form: f,
|
||||
name: :distributor_id_in,
|
||||
options: [],
|
||||
selected_option: params.dig(:q, :distributor_id_in),
|
||||
multiple: true,
|
||||
remote_url: admin_reports_search_distributors_url))
|
||||
.row
|
||||
.alpha.two.columns= label_tag nil, t(:report_producers)
|
||||
.omega.fourteen.columns= select_tag(:supplier_id_in, options_from_collection_for_select(@data.orders_suppliers, :id, :name, params[:supplier_id_in]), {class: "select2 fullwidth", multiple: true})
|
||||
.omega.fourteen.columns
|
||||
= render(SearchableDropdownComponent.new(name: :supplier_id_in,
|
||||
options: [],
|
||||
selected_option: params.dig(:supplier_id_in),
|
||||
multiple: true,
|
||||
remote_url: admin_reports_search_suppliers_url))
|
||||
|
||||
.row
|
||||
.alpha.two.columns= label_tag nil, t(:report_customers_cycle)
|
||||
.omega.fourteen.columns
|
||||
= f.select(:order_cycle_id_in, report_order_cycle_options(@data.order_cycles), {selected: params.dig(:q, :order_cycle_id_in)}, {class: "select2 fullwidth", multiple: true})
|
||||
|
||||
= render(SearchableDropdownComponent.new(form: f,
|
||||
name: :order_cycle_id_in,
|
||||
options: [],
|
||||
selected_option: params.dig(:q, :order_cycle_id_in),
|
||||
multiple: true,
|
||||
remote_url: admin_reports_search_order_cycles_url))
|
||||
.row
|
||||
.alpha.two.columns= label_tag nil, t(:fee_name)
|
||||
.omega.fourteen.columns
|
||||
= f.select(:enterprise_fee_id_in, fee_name_options(@report.search.result), {selected: params.dig(:q, :enterprise_fee_id_in)}, {class: "select2 fullwidth", multiple: true})
|
||||
= render(SearchableDropdownComponent.new(form: f,
|
||||
name: :enterprise_fee_id_in,
|
||||
options: [],
|
||||
selected_option: params.dig(:q, :enterprise_fee_id_in),
|
||||
multiple: true,
|
||||
remote_url: admin_reports_search_enterprise_fees_url(search_url_query)))
|
||||
|
||||
.row
|
||||
.alpha.two.columns= label_tag nil, t(:fee_owner)
|
||||
.omega.fourteen.columns
|
||||
= f.select(:enterprise_fee_owner_id_in, fee_owner_options(@report.search.result), {selected: params.dig(:q, :enterprise_fee_owner_id_in)}, {class: "select2 fullwidth", multiple: true})
|
||||
= render(SearchableDropdownComponent.new(form: f,
|
||||
name: :enterprise_fee_owner_id_in,
|
||||
options: [],
|
||||
selected_option: params.dig(:q, :enterprise_fee_owner_id_in),
|
||||
multiple: true,
|
||||
remote_url: admin_reports_search_enterprise_fee_owners_url(search_url_query)))
|
||||
|
||||
.row
|
||||
.alpha.two.columns= label_tag nil, t(:report_customers)
|
||||
.omega.fourteen.columns
|
||||
= f.select(:customer_id_in, customer_email_options(@data.order_customers), {selected: params.dig(:q, :customer_id_in)}, {class: "select2 fullwidth", multiple: true})
|
||||
= render(SearchableDropdownComponent.new(form: f,
|
||||
name: :customer_id_in,
|
||||
options: [],
|
||||
selected_option: params.dig(:q, :customer_id_in),
|
||||
multiple: true,
|
||||
remote_url: admin_reports_search_order_customers_url))
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
= cache do
|
||||
%img.spinner{ src: image_pack_path("images/spinning-circles.svg"), style: "max-width: 100%" }
|
||||
%img.spinner{ src: image_pack_path("spinning-circles.svg"), style: "max-width: 100%" }
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.row
|
||||
.small-12.text-center.columns
|
||||
%h1
|
||||
%img{src: image_pack_path("images/logo-white-notext.png"), title: Spree::Config.site_name}
|
||||
%img{src: image_pack_path("logo-white-notext.png"), title: Spree::Config.site_name}
|
||||
%br/
|
||||
%a.button.transparent{href: "/shops"}
|
||||
= t :home_shop
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.alert-box{ class: "#{type}" }
|
||||
= message
|
||||
- if local_assigns[:unconfirmed]
|
||||
%a{ "data-action": "login-modal#resend_confirmation", "data-tab": local_assigns[:tab] }
|
||||
= link_to spree_user_confirmation_path(spree_user: { email: }, tab: local_assigns[:tab]), data: { turbo_method: :post } do
|
||||
= t('devise.confirmations.resend_confirmation_email')
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#forgot-tab
|
||||
= form_with url: spree_user_password_path, scope: :spree_user, data: { remote: "true" } do |form|
|
||||
= form_with url: spree_user_password_path, scope: :spree_user, data: { turbo: true } do |form|
|
||||
.row
|
||||
.large-12.columns#forgot-feedback
|
||||
|
||||
.row
|
||||
.large-12.columns
|
||||
= form.label :email, t(:signup_email)
|
||||
= form.email_field :email, { tabindex: 1, inputmode: "email", "data-login-modal-target": "email", "data-action": "input->login-modal#emailOnInput" }
|
||||
= form.email_field :email, { tabindex: 1, inputmode: "email" }
|
||||
.row
|
||||
.large-12.columns
|
||||
= form.submit t(:reset_password), { class: "button primary", tabindex: 2 }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#login-content
|
||||
= form_with url: spree_user_session_path, scope: :spree_user, data: { remote: "true" } do |form|
|
||||
= form_with url: spree_user_session_path, scope: :spree_user, data: { turbo: true } do |form|
|
||||
.row
|
||||
.large-12.columns#login-feedback
|
||||
- confirmation_result = request.query_parameters[:validation]
|
||||
@@ -10,7 +10,7 @@
|
||||
.row
|
||||
.large-12.columns
|
||||
= form.label :email, t(:email)
|
||||
= form.email_field :email, { tabindex: 1, inputmode: "email", autocomplete: "off", "data-login-modal-target": "email", "data-action": "input->login-modal#emailOnInput" }
|
||||
= form.email_field :email, { tabindex: 1, inputmode: "email", autocomplete: "off" }
|
||||
.row
|
||||
.large-12.columns
|
||||
= form.label :password, t(:password)
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
- signup_form_user = Spree::User.new if local_assigns[:signup_form_user].nil?
|
||||
|
||||
#signup-tab
|
||||
= form_with model: signup_form_user, url: spree.account_path, scope: :user, data: { remote: "true" } do |form|
|
||||
= form_with model: signup_form_user, url: spree.account_path, scope: :user, data: { turbo: true } do |form|
|
||||
.row
|
||||
.large-12.columns#signup-feedback
|
||||
|
||||
.row
|
||||
.large-12.columns
|
||||
= form.label :email, t(:signup_email)
|
||||
= form.email_field :email, { tabindex: 1, "data-login-modal-target": "email", "data-action": "input->login-modal#emailOnInput" }
|
||||
= form.email_field :email, { tabindex: 1 }
|
||||
= form.error_message_on :email
|
||||
.row
|
||||
.large-12.columns
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
- else
|
||||
= favicon_link_tag "/favicon-staging.ico"
|
||||
%link{href: "https://fonts.googleapis.com/css?family=Roboto:400,300italic,400italic,300,700,700italic|Oswald:300,400,700", rel: "stylesheet", type: "text/css"}
|
||||
%link{href: asset_pack_path("static/fonts/OFN-v2.woff"), rel: "preload", as: "font", crossorigin: "anonymous"}
|
||||
%link{href: asset_pack_path("static/OFN-v2.woff"), rel: "preload", as: "font", crossorigin: "anonymous"}
|
||||
= render "layouts/matomo_tag"
|
||||
= language_meta_tags
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
|
||||
%title
|
||||
= Spree::Config[:site_name]
|
||||
= stylesheet_link_tag 'mail', media: "screen"
|
||||
= stylesheet_pack_tag "mail", media: "screen"
|
||||
%body{:bgcolor => "#FFFFFF" }
|
||||
- unless @hide_ofn_navigation
|
||||
%table.head-wrap
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
= csrf_meta_tags
|
||||
|
||||
%body.off-canvas{ style: "background-image: url(#{image_pack_path('images/tile-wide.png')})", "data-turbo": "false" }
|
||||
%body.off-canvas{ style: "background-image: url(#{image_pack_path('tile-wide.png')})", "data-turbo": "false" }
|
||||
.off-canvas-wrap{offcanvas: true}
|
||||
.inner-wrap
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
%p.word-wrap{"ng-if" => "::producer.whatsapp_phone"}
|
||||
%a{"ng-href" => "{{::producer.whatsapp_url}}", target: "_blank"}
|
||||
%img{ src: image_pack_path("images/social-logos/whatsapp.svg") }
|
||||
%img{ src: image_pack_path("social-logos/whatsapp.svg") }
|
||||
%span{"ng-bind" => "::producer.whatsapp_phone"}
|
||||
|
||||
%p.word-wrap{"ng-if" => "::producer.email_address"}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
%h4= t(".message")
|
||||
.row
|
||||
.small-12.medium-3.large-2.columns.text-right.hide-for-small-only
|
||||
%img{:src => image_pack_path("images/potatoes.png") }
|
||||
%img{:src => image_pack_path("potatoes.png") }
|
||||
.small-12.medium-9.large-10.columns
|
||||
%p
|
||||
= t(".text")
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
.row
|
||||
.small-12.columns.text-center
|
||||
.logo
|
||||
%img{src: image_pack_path("images/logo-white-notext.png") }
|
||||
%img{src: image_pack_path("logo-white-notext.png") }
|
||||
.row
|
||||
.small-12.medium-8.medium-offset-2.columns.text-center
|
||||
.alert-box
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
%span
|
||||
= t '.cart'
|
||||
%span.count
|
||||
%img{ src: image_pack_path("images/menu/icn-cart.svg") }
|
||||
%img{ src: image_pack_path("menu/icn-cart.svg") }
|
||||
%span
|
||||
{{ Cart.total_item_count() }}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
%nav.tab-bar.show-for-medium-down
|
||||
%section.left
|
||||
%a.left-off-canvas-toggle.menu-icon
|
||||
= image_pack_tag "images/menu/btn-menu-mobile.png"
|
||||
= image_pack_tag "menu/btn-menu-mobile.png"
|
||||
|
||||
%section.left
|
||||
.ofn-logo
|
||||
@@ -18,7 +18,7 @@
|
||||
%span
|
||||
= t '.cart'
|
||||
%span.count
|
||||
= image_pack_tag "images/menu/icn-cart.svg"
|
||||
= image_pack_tag "menu/icn-cart.svg"
|
||||
%span
|
||||
{{ Cart.total_item_count() }}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
%li.user-menu.has-dropdown.not-click
|
||||
|
||||
%a{href: "#", class: "top-bar--menu-item-with-icon"}
|
||||
%img{ src: image_pack_path("images/menu/icn-profile.svg") }
|
||||
%img{ src: image_pack_path("menu/icn-profile.svg") }
|
||||
%span
|
||||
= t '.profile'
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
= cache_with_locale do
|
||||
%li#login-link{ "data-controller": "login-modal" }
|
||||
%a{"auth": "login", "data-action": "click->login-modal#call" }
|
||||
%img{ src: image_pack_path("images/menu/icn-login.svg") }
|
||||
%img{ src: image_pack_path("menu/icn-login.svg") }
|
||||
%span
|
||||
= t 'label_login'
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"ng-debounce" => "200",
|
||||
"disable-enter-with-blur" => true}
|
||||
%a.clear{ type: 'button', "focus-search": true, "ng-show": 'query', "ng-click": 'clearQuery()' }
|
||||
= image_pack_tag "images/icn-close.png"
|
||||
= image_pack_tag "icn-close.png"
|
||||
|
||||
.hide-for-large-up
|
||||
%button{ type: 'button', "ng-click": 'toggleFilterSidebar()' }
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
%br
|
||||
- if current_distributor.whatsapp_phone.present?
|
||||
%a{href: current_distributor.whatsapp_url, target: "_blank" }
|
||||
%img{ src: image_pack_path("images/social-logos/whatsapp.svg") }
|
||||
%img{ src: image_pack_path("social-logos/whatsapp.svg") }
|
||||
= current_distributor.whatsapp_phone
|
||||
%br
|
||||
- if current_distributor.website.present?
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
= wicked_pdf_stylesheet_link_tag "mail"
|
||||
= pdf_stylesheet_pack_tag "mail"
|
||||
|
||||
%table{:width => "100%"}
|
||||
%tbody
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
= wicked_pdf_stylesheet_link_tag "mail"
|
||||
= pdf_stylesheet_pack_tag "mail"
|
||||
|
||||
%table{:width => "100%"}
|
||||
%tbody
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
= wicked_pdf_stylesheet_link_tag "mail"
|
||||
= pdf_stylesheet_pack_tag "mail"
|
||||
|
||||
%table{:width => "100%"}
|
||||
%tbody
|
||||
@@ -102,4 +102,4 @@
|
||||
= render partial: 'spree/admin/orders/_invoice/order_note'
|
||||
|
||||
.text-center
|
||||
= link_to_platform_terms
|
||||
= link_to_platform_terms
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
.alpha.four.columns
|
||||
= label :payment_method, :type, t('.provider')
|
||||
.omega.twelve.columns
|
||||
= collection_select(:payment_method, :type, @providers, :to_s, :clean_name, {}, { class: 'select2 fullwidth', 'provider-prefs-for' => "#{@object.id}"})
|
||||
= select(:payment_method, :type, payment_method_type_options(@providers), {}, { class: 'select2 fullwidth', required: true, placeholder: t("admin.choose"), 'provider-prefs-for' => "#{@object.id}"})
|
||||
|
||||
%div{"ng-include" => "include_html" }
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
- method.distributors.each do |distributor|
|
||||
= distributor.name
|
||||
%br/
|
||||
%td= method.class.clean_name
|
||||
%td= payment_method_type_name(method.class.name)
|
||||
- if spree_current_user.admin?
|
||||
%td.align-center= method.environment.to_s.titleize
|
||||
%td.align-center= method.display_on.blank? ? t('.both') : t('.' + method.display_on.to_s)
|
||||
|
||||
@@ -41,5 +41,5 @@
|
||||
%a.info.cvvLink{href: "/content/cvv", target: "_blank"}
|
||||
(#{t(:what_is_this)})
|
||||
.nine.columns
|
||||
= image_pack_tag 'images/credit_cards/credit_card.gif', class: 'credit-card-image'
|
||||
= image_pack_tag 'credit_cards/credit_card.gif', class: 'credit-card-image'
|
||||
.clear
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
= form_for @product, url: admin_product_url(@product, @url_filters), method: :put do |f|
|
||||
%fieldset.no-border-top
|
||||
.add_product_properties
|
||||
= image_pack_tag 'images/select2-spinner.gif', plugin: 'spree', style: 'display:none;', id: 'busy_indicator'
|
||||
= image_pack_tag 'select2-spinner.gif', plugin: 'spree', style: 'display:none;', id: 'busy_indicator'
|
||||
|
||||
%table.index.sortable{"data-sortable-link" => update_positions_admin_product_product_properties_url}
|
||||
%thead
|
||||
|
||||
@@ -11,6 +11,6 @@
|
||||
- databaseurl = "#{admin_states_path(format: :js)}?country_id="
|
||||
%select#country.observe_field.select2.fullwidth{"data-base-url" => databaseurl, "data-update" => "#state-list"}
|
||||
= options_from_collection_for_select(@countries, :id, :name, @country.id)
|
||||
= image_pack_tag 'images/select2-spinner.gif', plugin: 'spree', style: 'display:none;', id: 'busy_indicator'
|
||||
= image_pack_tag 'select2-spinner.gif', plugin: 'spree', style: 'display:none;', id: 'busy_indicator'
|
||||
#state-list
|
||||
= render partial: 'state_list'
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Controller } from "stimulus";
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["background", "modal", "email"];
|
||||
static values = { email: String };
|
||||
static targets = ["background", "modal"];
|
||||
|
||||
connect() {
|
||||
if (this.hasModalTarget) {
|
||||
@@ -19,13 +18,6 @@ export default class extends Controller {
|
||||
window.dispatchEvent(new Event("login:modal:open"));
|
||||
}
|
||||
|
||||
emailOnInput(event) {
|
||||
this.emailValue = event.currentTarget.value;
|
||||
this.emailTargets.forEach((element) => {
|
||||
element.value = this.emailValue;
|
||||
});
|
||||
}
|
||||
|
||||
open = () => {
|
||||
if (!location.hash.substr(1).includes("/login")) {
|
||||
history.pushState({}, "", "#/login");
|
||||
@@ -57,19 +49,6 @@ export default class extends Controller {
|
||||
}, 200);
|
||||
}
|
||||
|
||||
resend_confirmation(event) {
|
||||
fetch("/user/spree_user/confirmation", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
spree_user: { email: this.emailValue },
|
||||
tab: event.currentTarget.dataset.tab,
|
||||
}),
|
||||
headers: { "Content-type": "application/json; charset=UTF-8" },
|
||||
})
|
||||
.then((data) => data.json())
|
||||
.then(CableReady.perform);
|
||||
}
|
||||
|
||||
returnHome() {
|
||||
window.location = "/";
|
||||
}
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import { Controller } from "stimulus";
|
||||
import TomSelect from "tom-select/dist/esm/tom-select.complete";
|
||||
import showHttpError from "../../webpacker/js/services/show_http_error";
|
||||
|
||||
export default class extends Controller {
|
||||
static values = { options: Object, placeholder: String };
|
||||
static values = {
|
||||
options: Object,
|
||||
placeholder: String,
|
||||
remoteUrl: String,
|
||||
};
|
||||
|
||||
connect(options = {}) {
|
||||
this.control = new TomSelect(this.element, {
|
||||
let tomSelectOptions = {
|
||||
maxItems: 1,
|
||||
maxOptions: null,
|
||||
plugins: ["dropdown_input"],
|
||||
@@ -16,7 +21,13 @@ export default class extends Controller {
|
||||
},
|
||||
...this.optionsValue,
|
||||
...options,
|
||||
});
|
||||
};
|
||||
|
||||
if (this.remoteUrlValue) {
|
||||
this.#addRemoteOptions(tomSelectOptions);
|
||||
}
|
||||
|
||||
this.control = new TomSelect(this.element, tomSelectOptions);
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
@@ -29,4 +40,78 @@ export default class extends Controller {
|
||||
const optionsArray = [...this.element.options];
|
||||
return optionsArray.find((option) => [null, ""].includes(option.value))?.text;
|
||||
}
|
||||
|
||||
#buildUrl(query, page = 1) {
|
||||
const url = new URL(this.remoteUrlValue, window.location.origin);
|
||||
url.searchParams.set("q", query);
|
||||
url.searchParams.set("page", page);
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
#fetchOptions(query, callback) {
|
||||
const url = this.control.getUrl(query);
|
||||
|
||||
fetch(url)
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
showHttpError(response.status);
|
||||
throw response;
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then((json) => {
|
||||
/**
|
||||
* Expected API shape:
|
||||
* {
|
||||
* results: [{ value, label }],
|
||||
* pagination: { more: boolean }
|
||||
* }
|
||||
*/
|
||||
if (json.pagination?.more) {
|
||||
const currentUrl = new URL(url);
|
||||
const currentPage = parseInt(currentUrl.searchParams.get("page") || "1");
|
||||
const nextUrl = this.#buildUrl(query, currentPage + 1);
|
||||
this.control.setNextUrl(query, nextUrl);
|
||||
}
|
||||
|
||||
callback(json.results || []);
|
||||
})
|
||||
.catch((error) => {
|
||||
callback();
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
|
||||
#addRemoteOptions(options) {
|
||||
this.openedByClick = false;
|
||||
|
||||
options.firstUrl = (query) => {
|
||||
return this.#buildUrl(query, 1);
|
||||
};
|
||||
|
||||
options.load = this.#fetchOptions.bind(this);
|
||||
|
||||
options.onFocus = function () {
|
||||
this.control.load("", () => {});
|
||||
}.bind(this);
|
||||
|
||||
options.onDropdownOpen = function () {
|
||||
this.openedByClick = true;
|
||||
}.bind(this);
|
||||
|
||||
options.onType = function () {
|
||||
this.openedByClick = false;
|
||||
}.bind(this);
|
||||
|
||||
// As per TomSelect source code, Loading state is shown on the UI when this function returns true.
|
||||
// By default it shows loading state only when there is some input in the search box.
|
||||
// We want to show loading state on focus as well (when there is no input) to indicate that options are being loaded.
|
||||
options.shouldLoad = function (query) {
|
||||
return this.openedByClick || query.length > 0;
|
||||
}.bind(this);
|
||||
|
||||
options.valueField = "value";
|
||||
options.labelField = "label";
|
||||
options.searchField = "label";
|
||||
}
|
||||
}
|
||||
|
||||
3
app/webpacker/css/mail/all.scss
Normal file
3
app/webpacker/css/mail/all.scss
Normal file
@@ -0,0 +1,3 @@
|
||||
@import '../admin/globals/palette.scss';
|
||||
@import 'email';
|
||||
@import 'payments_list';
|
||||
@@ -9,7 +9,7 @@ document.addEventListener("turbo:frame-missing", (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
// show error message instead
|
||||
showError(event.detail.response?.status);
|
||||
showHttpError(event.detail.response?.status);
|
||||
});
|
||||
|
||||
document.addEventListener("turbo:submit-end", (event) => {
|
||||
|
||||
1
app/webpacker/packs/mail.scss
Normal file
1
app/webpacker/packs/mail.scss
Normal file
@@ -0,0 +1 @@
|
||||
@import "../css/mail/all.scss";
|
||||
@@ -41,7 +41,7 @@ FileUtils.chdir APP_ROOT do
|
||||
system! "rm -f tmp/invoices/*.pdf"
|
||||
system! "rm -f tmp/javascripts/*.js"
|
||||
system! "rm -f tmp/karma_unit.js*"
|
||||
system! "rm -f tmp/product_import-*"
|
||||
system! "rm -rf tmp/product_import-*"
|
||||
|
||||
puts "\n== Removing any precompiled assets that would be out of date now =="
|
||||
system! "rm -rf public/assets/"
|
||||
|
||||
@@ -19,6 +19,5 @@ Rails.application.config.assets.precompile += [
|
||||
'web/all.js',
|
||||
'darkswarm/all.js',
|
||||
'shared/*',
|
||||
'mail.scss',
|
||||
'*.jpg', '*.jpeg', '*.png', '*.gif' '*.svg',
|
||||
]
|
||||
|
||||
@@ -2,16 +2,27 @@ require_relative 'spree'
|
||||
|
||||
Rails.application.reloader.to_prepare do
|
||||
# See: https://github.com/openfoodfoundation/db2fog
|
||||
DB2Fog.config = {
|
||||
if ENV['S3_BACKUPS_HOST'].present?
|
||||
DB2Fog.config = {
|
||||
aws_access_key_id: ENV['S3_BACKUPS_ACCESS_KEY'],
|
||||
aws_secret_access_key: ENV['S3_BACKUPS_SECRET'],
|
||||
directory: ENV['S3_BACKUPS_BUCKET'],
|
||||
provider: 'AWS',
|
||||
scheme: ENV['S3_BACKUPS_SCHEME'],
|
||||
host: ENV['S3_BACKUPS_HOST']
|
||||
}
|
||||
else
|
||||
DB2Fog.config = {
|
||||
:aws_access_key_id => Spree::Config[:s3_access_key],
|
||||
:aws_secret_access_key => Spree::Config[:s3_secret],
|
||||
:directory => ENV['S3_BACKUPS_BUCKET'],
|
||||
:provider => 'AWS'
|
||||
}
|
||||
}
|
||||
|
||||
region = ENV['S3_BACKUPS_REGION'] || ENV['S3_REGION']
|
||||
region = ENV['S3_BACKUPS_REGION'] || ENV['S3_REGION']
|
||||
|
||||
# If no region is defined we leave this config key undefined (instead of nil),
|
||||
# so that db2fog correctly applies it's default
|
||||
DB2Fog.config[:region] = region if region
|
||||
# If no region is defined we leave this config key undefined (instead of nil),
|
||||
# so that db2fog correctly applies it's default
|
||||
DB2Fog.config[:region] = region if region
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3765,6 +3765,7 @@ ar:
|
||||
alt_text: "نص بديل"
|
||||
thumbnail: "الباقة"
|
||||
back_to_images_list: "العودة إلى قائمة الصور"
|
||||
api_key: "مفتاح API"
|
||||
email: البريد الإلكتروني
|
||||
account_updated: "تم تحديث الحساب!"
|
||||
email_updated: "سيتم تحديث الحساب بمجرد تأكيد البريد الإلكتروني الجديد."
|
||||
@@ -4065,9 +4066,7 @@ ar:
|
||||
providers:
|
||||
provider: "مزود"
|
||||
check: "النقد / التحويل الإلكتروني / إلخ. (المدفوعات التي لا تتطلب المصادقة التلقائية)"
|
||||
pin: "المدفوعات دبوس"
|
||||
paypalexpress: "باي بال اكسبريس"
|
||||
stripeconnect: "Stripe SCA"
|
||||
stripesca: "Stripe SCA"
|
||||
payments:
|
||||
source_forms:
|
||||
|
||||
@@ -3645,6 +3645,7 @@ ca:
|
||||
alt_text: "Text alternatiu"
|
||||
thumbnail: "Miniatura"
|
||||
back_to_images_list: "Torna a la llista d’imatges"
|
||||
api_key: "Clau API"
|
||||
email: Correu electrònic
|
||||
account_updated: "Compte actualitzat!"
|
||||
email_updated: "El compte s’actualitzarà un cop es confirmi el nou correu electrònic."
|
||||
@@ -3943,9 +3944,7 @@ ca:
|
||||
providers:
|
||||
provider: "Proveïdor"
|
||||
check: "Efectiu / transferència / etc. (pagaments per als quals no és necessària la validació automàtica)"
|
||||
pin: "Pin Payments"
|
||||
paypalexpress: "PayPal Express"
|
||||
stripeconnect: "Stripe (obsolet)"
|
||||
stripesca: "Stripe SCA"
|
||||
payments:
|
||||
source_forms:
|
||||
|
||||
@@ -4105,6 +4105,7 @@ cy:
|
||||
alt_text: "Testun Amgen"
|
||||
thumbnail: "Cryno-lun"
|
||||
back_to_images_list: "Yn ôl i'r Rhestr Delweddau"
|
||||
api_key: "Allwedd API"
|
||||
email: E-bost
|
||||
account_updated: "Diweddarwyd y cyfrif!"
|
||||
email_updated: "Bydd y cyfrif yn cael ei ddiweddaru ar ôl cadarnhau'r cyfeiriad e-bost newydd."
|
||||
@@ -4420,9 +4421,7 @@ cy:
|
||||
providers:
|
||||
provider: "Darparwr"
|
||||
check: "Arian/TRhE/ac ati (taliadau lle nad oes angen dilysu awtomatig)."
|
||||
pin: "Taliadau Pin"
|
||||
paypalexpress: "PayPal Express"
|
||||
stripeconnect: "Stripe"
|
||||
stripesca: "Stripe SCA"
|
||||
payments:
|
||||
source_forms:
|
||||
|
||||
@@ -3976,9 +3976,7 @@ de_CH:
|
||||
providers:
|
||||
provider: "Anbieter"
|
||||
check: "Bargeld, EC etc. (Zahlungen, für die keine automatische Validierung erforderlich ist)"
|
||||
pin: "Pin Zahlungen"
|
||||
paypalexpress: "PayPal Express"
|
||||
stripeconnect: "Stripe"
|
||||
stripesca: "Stripe SCA"
|
||||
payments:
|
||||
source_forms:
|
||||
|
||||
@@ -3873,6 +3873,7 @@ de_DE:
|
||||
alt_text: "Alternativtext"
|
||||
thumbnail: "Miniaturansicht"
|
||||
back_to_images_list: "Zurück zur Bilderliste"
|
||||
api_key: "API-Schlüssel"
|
||||
email: E-Mail-Adresse
|
||||
account_updated: "Konto aktualisiert!"
|
||||
email_updated: "Das Konto wird aktualisiert, sobald die neue E-Mail-Adresse bestätigt wurde."
|
||||
@@ -4183,9 +4184,7 @@ de_DE:
|
||||
providers:
|
||||
provider: "Anbieter"
|
||||
check: "Bargeld, EC etc. (Zahlungen, für die keine automatische Validierung erforderlich ist)"
|
||||
pin: "Pin Zahlungen"
|
||||
paypalexpress: "PayPal Express"
|
||||
stripeconnect: "Stripe"
|
||||
stripesca: "Stripe SCA"
|
||||
payments:
|
||||
source_forms:
|
||||
|
||||
@@ -3867,6 +3867,7 @@ el:
|
||||
alt_text: "Εναλλακτικό Κείμενο"
|
||||
thumbnail: "Μικρογραφία (Thumnail) "
|
||||
back_to_images_list: "Επιστροφή στη λίστα εικόνων"
|
||||
api_key: "Κλειδί API"
|
||||
email: ΗΛΕΚΤΡΟΝΙΚΗ ΔΙΕΥΘΥΝΣΗ
|
||||
account_updated: "Ο λογαριασμός ενημερώθηκε!"
|
||||
email_updated: "Ο λογαριασμός θα ενημερωθεί μόλις επιβεβαιωθεί το νέο μήνυμα ηλεκτρονικού ταχυδρομείου."
|
||||
@@ -4181,9 +4182,7 @@ el:
|
||||
providers:
|
||||
provider: "Προμηθευτής"
|
||||
check: "Μετρητά/EFT/κλπ. (πληρωμές για τις οποίες δεν απαιτείται αυτόματη επικύρωση)"
|
||||
pin: "Καρφίτσωμα πληρωμών"
|
||||
paypalexpress: "PayPal Express"
|
||||
stripeconnect: "Ταινία"
|
||||
stripesca: "Stripe SCA"
|
||||
payments:
|
||||
source_forms:
|
||||
|
||||
@@ -288,6 +288,9 @@ en:
|
||||
success_code:
|
||||
disconnected: "Stripe account disconnected."
|
||||
|
||||
taler:
|
||||
order_status:
|
||||
claimed: "The payment request expired. Please try again."
|
||||
activemodel:
|
||||
errors:
|
||||
messages:
|
||||
@@ -3502,6 +3505,8 @@ en:
|
||||
payment_processing_failed: "Payment could not be processed, please check the details you entered"
|
||||
payment_method_not_supported: "That payment method is unsupported. Please choose another one."
|
||||
payment_updated: "Payment Updated"
|
||||
payment_method_taler:
|
||||
order_summary: "Open Food Network order"
|
||||
cannot_perform_operation: "Could not update the payment"
|
||||
action_required: "Action required"
|
||||
tag_rules: "Tag Rules"
|
||||
@@ -4344,6 +4349,10 @@ en:
|
||||
thumbnail: "Thumbnail"
|
||||
back_to_images_list: "Back To Images List"
|
||||
|
||||
# Attributes of the Taler payment gateway
|
||||
backend_url: "Backend URL"
|
||||
api_key: "API key"
|
||||
|
||||
# TODO: remove `email` key once we get to Spree 2.0
|
||||
email: Email
|
||||
# TODO: remove 'account_updated' key once we get to Spree 2.0
|
||||
@@ -4664,10 +4673,9 @@ en:
|
||||
providers:
|
||||
provider: "Provider"
|
||||
check: "Cash/EFT/etc. (payments for which automatic validation is not required)"
|
||||
pin: "Pin Payments"
|
||||
paypalexpress: "PayPal Express"
|
||||
stripeconnect: "Stripe"
|
||||
stripesca: "Stripe SCA"
|
||||
taler: "Taler"
|
||||
payments:
|
||||
source_forms:
|
||||
stripe:
|
||||
|
||||
@@ -246,6 +246,9 @@ en_CA:
|
||||
disconnect_failure: "Failed to disconnecct Stripe."
|
||||
success_code:
|
||||
disconnected: "Stripe account disconnected."
|
||||
taler:
|
||||
order_status:
|
||||
claimed: "The payment request expired. Please try again."
|
||||
activemodel:
|
||||
errors:
|
||||
messages:
|
||||
@@ -3358,6 +3361,8 @@ en_CA:
|
||||
payment_processing_failed: "Payment could not be processed, please check the details you entered."
|
||||
payment_method_not_supported: "That payment method is unsupported. Please choose another one."
|
||||
payment_updated: "Payment Updated"
|
||||
payment_method_taler:
|
||||
order_summary: "Open Food Network order"
|
||||
cannot_perform_operation: "Could not update the payment"
|
||||
action_required: "Action required"
|
||||
tag_rules: "Tag Rules"
|
||||
@@ -4171,6 +4176,8 @@ en_CA:
|
||||
alt_text: "Alternative Text"
|
||||
thumbnail: "Thumbnail"
|
||||
back_to_images_list: "Back to Images List"
|
||||
backend_url: "Backend URL"
|
||||
api_key: "API key"
|
||||
email: Email
|
||||
account_updated: "Account updated!"
|
||||
email_updated: "The account will be updated once the new email is confirmed."
|
||||
@@ -4487,10 +4494,9 @@ en_CA:
|
||||
providers:
|
||||
provider: "Provider"
|
||||
check: "Cash/EFT/Bank Transfer etc. (payments for which automatic validation is not required)"
|
||||
pin: "Pin Payments (Only applicable to users in Australia)"
|
||||
paypalexpress: "PayPal Express"
|
||||
stripeconnect: "Stripe For Deletion"
|
||||
stripesca: "Stripe SCA"
|
||||
taler: "Taler"
|
||||
payments:
|
||||
source_forms:
|
||||
stripe:
|
||||
|
||||
@@ -246,6 +246,9 @@ en_FR:
|
||||
disconnect_failure: "Failed to disconnect Stripe."
|
||||
success_code:
|
||||
disconnected: "Stripe account disconnected."
|
||||
taler:
|
||||
order_status:
|
||||
claimed: "The payment request expired. Please try again."
|
||||
activemodel:
|
||||
errors:
|
||||
messages:
|
||||
@@ -3358,6 +3361,8 @@ en_FR:
|
||||
payment_processing_failed: "Payment could not be processed, please check the details you entered"
|
||||
payment_method_not_supported: "That payment method is unsupported. Please choose another one."
|
||||
payment_updated: "Payment Updated"
|
||||
payment_method_taler:
|
||||
order_summary: "Open Food Network order"
|
||||
cannot_perform_operation: "Could not update the payment"
|
||||
action_required: "Action required"
|
||||
tag_rules: "Tag Rules"
|
||||
@@ -4172,6 +4177,8 @@ en_FR:
|
||||
alt_text: "Alternative Text"
|
||||
thumbnail: "Thumbnail"
|
||||
back_to_images_list: "Back To Images List"
|
||||
backend_url: "Backend URL"
|
||||
api_key: "API key"
|
||||
email: Email
|
||||
account_updated: "Account updated!"
|
||||
email_updated: "The account will be updated once the new email is confirmed."
|
||||
@@ -4488,10 +4495,9 @@ en_FR:
|
||||
providers:
|
||||
provider: "Provider"
|
||||
check: "Cash/EFT/etc. (payments for which automatic validation is not required)"
|
||||
pin: "Pin Payments"
|
||||
paypalexpress: "PayPal Express"
|
||||
stripeconnect: "Stripe (old version)"
|
||||
stripesca: "Stripe"
|
||||
taler: "Taler"
|
||||
payments:
|
||||
source_forms:
|
||||
stripe:
|
||||
|
||||
@@ -115,6 +115,67 @@ en_GB:
|
||||
blank: "can't be blank"
|
||||
too_short: "is too short (minimum is %{count} characters)"
|
||||
errors:
|
||||
messages:
|
||||
content_type_invalid:
|
||||
one: "has an invalid content type (authorised content type is %{authorized_human_content_types})"
|
||||
other: "has an invalid content type (authorised content types are\n%{authorized_human_content_types})"
|
||||
content_type_spoofed:
|
||||
one: "has a content type that is not equivalent to the one that is detected through its content (authorised content type is %{authorized_human_content_types})"
|
||||
other: "has a content type that is not equivalent to the one that is detected through its content (authorised content types are %{authorized_human_content_types})"
|
||||
file_size_not_less_than: "file size must be less than %{max} (current size is %{file_size})"
|
||||
file_size_not_less_than_or_equal_to: "file size must be less than or equal to %{max} (current size is %{file_size})"
|
||||
file_size_not_greater_than: "file size must be greater than %{min} (current size is %{file_size})"
|
||||
file_size_not_greater_than_or_equal_to: "file size must be greater than or equal to %{min} (current size is %{file_size})"
|
||||
file_size_not_between: "file size must be between %{min} and %{max} (current size is %{file_size})"
|
||||
file_size_not_equal_to: "file size must be equal to %{exact} (current size is %{file_size})"
|
||||
total_file_size_not_less_than: "total file size must be less than %{max} (current size is %{total_file_size})"
|
||||
total_file_size_not_less_than_or_equal_to: "total file size must be less than or equal to %{max} (current size is %{total_file_size})"
|
||||
total_file_size_not_greater_than: "total file size must be greater than %{min} (current size is %{total_file_size})"
|
||||
total_file_size_not_greater_than_or_equal_to: "total file size must be greater than or equal to %{min} (current size is %{total_file_size})"
|
||||
total_file_size_not_between: "total file size must be between %{min} and %{max} (current size is %{total_file_size})"
|
||||
total_file_size_not_equal_to: "total file size must be equal to %{exact} (current size is %{total_file_size})"
|
||||
duration_not_less_than: "duration must be less than %{max} (current duration is %{duration})"
|
||||
duration_not_less_than_or_equal_to: "duration must be less than or equal to %{max} (current duration is %{duration})"
|
||||
duration_not_greater_than: "duration must be greater than %{min} (current duration is %{duration})"
|
||||
duration_not_greater_than_or_equal_to: "duration must be greater than or equal to %{min} (current duration is %{duration})"
|
||||
duration_not_between: "duration must be between %{min} and %{max} (current duration is %{duration})"
|
||||
duration_not_equal_to: "duration must be equal to %{exact} (current duration is %{duration})"
|
||||
limit_out_of_range:
|
||||
zero: "no files attached (must have between %{min} and %{max}files)"
|
||||
one: "only 1 file attached (must have between %{min} and %{max}files)"
|
||||
other: "total number of files must be between %{min} and %{max} files (there are %{count}files attached)"
|
||||
limit_min_not_reached:
|
||||
zero: "no files attached (must have at least %{min} files)"
|
||||
one: "only 1 file attached (must have at least %{min} files)"
|
||||
other: "%{count} files attached (must have at least %{min} files)"
|
||||
limit_max_exceeded:
|
||||
zero: "no files attached (maximum is %{max} files)"
|
||||
one: "too many files attached (maximum is %{max} files, got %{count})"
|
||||
other: "too many files attached (maximum is %{max} files, got %{count})"
|
||||
attachment_missing: "is missing its attachment"
|
||||
media_metadata_missing: "is not a valid media file"
|
||||
dimension_min_not_included_in: "must be greater than or equal to %{width} x %{height} pixels"
|
||||
dimension_max_not_included_in: "must be less than or equal to %{width} x %{height} pixels"
|
||||
dimension_width_not_included_in: "width is not included between %{min} and %{max} pixels"
|
||||
dimension_height_not_included_in: "height is not included between %{min} and %{max} pixels"
|
||||
dimension_width_not_greater_than_or_equal_to: "width must be greater than or equal to %{length} pixels"
|
||||
dimension_height_not_greater_than_or_equal_to: "height must be greater than or equal to %{length} pixels"
|
||||
dimension_width_not_less_than_or_equal_to: "width must be less than or equal to %{length} pixels"
|
||||
dimension_height_not_less_than_or_equal_to: "height must be less than or equal to %{length} pixels"
|
||||
dimension_width_not_equal_to: "width must be equal to %{length} pixels"
|
||||
dimension_height_not_equal_to: "height must be equal to %{length} pixels"
|
||||
aspect_ratio_not_square: "must be square (current file is %{width}x%{height}px)"
|
||||
aspect_ratio_not_portrait: "must be portrait (current file is %{width}x%{height}px)"
|
||||
aspect_ratio_not_landscape: "must be landscape (current file is %{width}x%{height}px)"
|
||||
aspect_ratio_not_x_y: "must be %{authorized_aspect_ratios} (current file is %{width}x%{height}px)"
|
||||
aspect_ratio_invalid: "has an invalid aspect ratio (valid aspect ratios are %{authorized_aspect_ratios})"
|
||||
file_not_processable: "is not identified as a valid media file"
|
||||
pages_not_less_than: "page count must be less than %{max} (current page count is %{pages})"
|
||||
pages_not_less_than_or_equal_to: "page count must be less than or equal to %{max} (current page count is %{pages})"
|
||||
pages_not_greater_than: "page count must be greater than %{min} (current page count is %{pages})"
|
||||
pages_not_greater_than_or_equal_to: "page count must be greater than or equal to %{min} (current page count is %{pages})"
|
||||
pages_not_between: "page count must be between %{min} and %{max} (current page count is %{pages})"
|
||||
pages_not_equal_to: "page count must be equal to %{exact} (current page count is %{pages})"
|
||||
not_found:
|
||||
title: "The page you were looking for doesn't exist (404)"
|
||||
message_html: "<b>Please try again</b> <p>This might be a temporary problem. Please click the back button to return to the previous screen or go back to <a href='/'>Home</a> and try again.</p> <b>Contact support</b> <p>If the problem persists or is urgent, please tell us about it. Find our contact details from the global <a href='https://openfoodnetwork.org/ofn-local/' target='blank'>Open Food Network Local page</a>.</p> <p>It really helps us if you can give as much detail as possible about what the missing page is about.</p>"
|
||||
@@ -185,6 +246,9 @@ en_GB:
|
||||
disconnect_failure: "Failed to disconnect Stripe."
|
||||
success_code:
|
||||
disconnected: "Stripe account disconnected."
|
||||
taler:
|
||||
order_status:
|
||||
claimed: "The payment request expired. Please try again."
|
||||
activemodel:
|
||||
errors:
|
||||
messages:
|
||||
@@ -520,6 +584,7 @@ en_GB:
|
||||
errors:
|
||||
vine_api: "There was an error communicating with the API, please try again later."
|
||||
invalid_voucher: "The voucher is not valid"
|
||||
expired: "The voucher has expired"
|
||||
not_found_voucher: "Sorry, we couldn't find that voucher, please check the code."
|
||||
vine_voucher_redeemer_service:
|
||||
errors:
|
||||
@@ -934,6 +999,10 @@ en_GB:
|
||||
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
|
||||
@@ -2374,9 +2443,9 @@ en_GB:
|
||||
order_includes_tax: (includes tax)
|
||||
order_payment_paypal_successful: Your payment via PayPal has been processed successfully.
|
||||
order_hub_info: Hub info
|
||||
order_back_to_store: Back To Store
|
||||
order_back_to_cart: Back To Cart
|
||||
order_back_to_website: Back To Website
|
||||
order_back_to_store: Back to shop
|
||||
order_back_to_cart: Back to cart
|
||||
order_back_to_website: Back to website
|
||||
checkout_details_title: Checkout Details
|
||||
checkout_payment_title: Checkout Payment
|
||||
checkout_summary_title: Checkout Summary
|
||||
@@ -3292,11 +3361,13 @@ en_GB:
|
||||
payment_processing_failed: "Payment could not be processed, please check the details you entered"
|
||||
payment_method_not_supported: "That payment method is unsupported. Please choose another one."
|
||||
payment_updated: "Payment Updated"
|
||||
payment_method_taler:
|
||||
order_summary: "Open Food Network order"
|
||||
cannot_perform_operation: "Could not update the payment"
|
||||
action_required: "Action required"
|
||||
tag_rules: "Tag Rules"
|
||||
enterprise_fee_whole_order: Whole order
|
||||
enterprise_fee_by_name: "%{name} fee by %{role}%{enterprise_name}"
|
||||
enterprise_fee_by_name: "%{name} fee by %{role} %{enterprise_name}"
|
||||
validation_msg_relationship_already_established: "^That relationship is already established."
|
||||
validation_msg_at_least_one_hub: "^At least one hub must be selected"
|
||||
validation_msg_tax_category_cant_be_blank: "^Tax Category can't be blank"
|
||||
@@ -3337,6 +3408,7 @@ en_GB:
|
||||
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."
|
||||
order_cycle_closed_next_steps: "The order cycle you've selected has just closed. Please contact us to complete your order #\n%{order_number}!"
|
||||
back_to_orders_list: "Back To Orders List"
|
||||
no_orders_found: "No Orders Found"
|
||||
order_information: "Order Information"
|
||||
@@ -3911,6 +3983,8 @@ en_GB:
|
||||
destroy:
|
||||
success: Webhook endpoint successfully deleted
|
||||
error: Webhook endpoint failed to delete
|
||||
test:
|
||||
success: Some test data will be sent to the webhook url
|
||||
spree:
|
||||
order_updated: "Order Updated"
|
||||
cannot_perform_operation: "Can not perform this operation"
|
||||
@@ -4017,6 +4091,7 @@ en_GB:
|
||||
logourl: "Logo url"
|
||||
are_you_sure_delete: "Are you sure you want to delete this record?"
|
||||
confirm_delete: "Confirm Deletion"
|
||||
tag_rule: "Tag Rule"
|
||||
voucher: "Voucher"
|
||||
configurations: "Configurations"
|
||||
general_settings: "General Settings"
|
||||
@@ -4108,6 +4183,8 @@ en_GB:
|
||||
alt_text: "Alternative Text"
|
||||
thumbnail: "Thumbnail"
|
||||
back_to_images_list: "Back To Images List"
|
||||
backend_url: "Backend URL"
|
||||
api_key: "API key"
|
||||
email: Email
|
||||
account_updated: "Account updated!"
|
||||
email_updated: "The account will be updated once the new email is confirmed."
|
||||
@@ -4424,10 +4501,9 @@ en_GB:
|
||||
providers:
|
||||
provider: "Provider"
|
||||
check: "Cash/EFT/etc. (payments for which automatic validation is not required)"
|
||||
pin: "Pin Payments"
|
||||
paypalexpress: "PayPal Express"
|
||||
stripeconnect: "depreciated card payment method (no longer in use in UK)"
|
||||
stripesca: "Stripe SCA "
|
||||
taler: "Taler"
|
||||
payments:
|
||||
source_forms:
|
||||
stripe:
|
||||
@@ -4884,6 +4960,7 @@ en_GB:
|
||||
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
|
||||
@@ -4899,6 +4976,8 @@ en_GB:
|
||||
create_placeholder: Enter the URL of the remote webhook endpoint
|
||||
event_types:
|
||||
order_cycle_opened: Order Cycle Opened
|
||||
payment_status_changed: Post webhook on Payment status change
|
||||
test_endpoint: Test webhook endpoint
|
||||
invisible_captcha:
|
||||
sentence_for_humans: "Please leave empty"
|
||||
timestamp_error_message: "Please try again after 5 seconds."
|
||||
|
||||
@@ -3971,6 +3971,7 @@ en_IE:
|
||||
alt_text: "Alternative Text"
|
||||
thumbnail: "Thumbnail"
|
||||
back_to_images_list: "Back To Images List"
|
||||
api_key: "API key"
|
||||
email: Email
|
||||
account_updated: "Account updated!"
|
||||
email_updated: "The account will be updated once the new email is confirmed."
|
||||
@@ -4286,9 +4287,7 @@ en_IE:
|
||||
providers:
|
||||
provider: "Provider"
|
||||
check: "Cash/EFT/etc. (payments for which automatic validation is not required)"
|
||||
pin: "Pin Payments"
|
||||
paypalexpress: "PayPal Express"
|
||||
stripeconnect: "Stripe (Obsolete version)"
|
||||
stripesca: "Stripe"
|
||||
payments:
|
||||
source_forms:
|
||||
|
||||
@@ -3752,9 +3752,7 @@ en_NZ:
|
||||
providers:
|
||||
provider: "Provider"
|
||||
check: "Cash/EFT/etc. (payments for which automatic validation is not required)"
|
||||
pin: "Pin Payments"
|
||||
paypalexpress: "PayPal Express"
|
||||
stripeconnect: "Stripe"
|
||||
stripesca: "Stripe SCA"
|
||||
payments:
|
||||
source_forms:
|
||||
|
||||
@@ -3789,9 +3789,7 @@ en_US:
|
||||
providers:
|
||||
provider: "Provider"
|
||||
check: "Cash/EFT/etc. (payments for which automatic validation is not required)"
|
||||
pin: "Pin Payments"
|
||||
paypalexpress: "PayPal Express"
|
||||
stripeconnect: "retired, please use Stripe SCA"
|
||||
stripesca: "Stripe SCA"
|
||||
payments:
|
||||
source_forms:
|
||||
|
||||
@@ -489,7 +489,7 @@ es:
|
||||
none: Ninguno
|
||||
notes: Notas
|
||||
error: Error
|
||||
voucher: Bono
|
||||
voucher: Cupón
|
||||
processing_payment: "Procesando el pago..."
|
||||
no_pending_payments: "No tiene pagos pendientes"
|
||||
invalid_payment_state: "Estado de pago inválido: %{state}"
|
||||
@@ -519,12 +519,13 @@ es:
|
||||
vine_voucher_validator_service:
|
||||
errors:
|
||||
vine_api: "Se ha producido un error en la comunicación con la API, inténtelo de nuevo más tarde."
|
||||
invalid_voucher: "El bono no es válido"
|
||||
not_found_voucher: "Lo sentimos, no hemos podido encontrar ese vale, por favor, compruebe el código."
|
||||
invalid_voucher: "El cupón no es válido"
|
||||
expired: "El cupón se ha caducado"
|
||||
not_found_voucher: "Lo sentimos, no hemos podido encontrar ese cupón, por favor, compruebe el código."
|
||||
vine_voucher_redeemer_service:
|
||||
errors:
|
||||
vine_api: "Ha habido un error en la comunicación con el API"
|
||||
redeeming_failed: "Error al canjear el bono"
|
||||
redeeming_failed: "Error al canjear el cupón"
|
||||
actions:
|
||||
create_and_add_another: "Crear y agregar otro"
|
||||
create: "Crear"
|
||||
@@ -718,6 +719,7 @@ es:
|
||||
enabled_legend: "Aplicaciones conectadas habilitadas"
|
||||
connected_apps_enabled:
|
||||
discover_regen: Descubrir el Portal Regenerativo
|
||||
vine: Voucher Integration Engine (VINE)
|
||||
update:
|
||||
resource: Ajustes de la aplicación conectada
|
||||
customers:
|
||||
@@ -1078,6 +1080,7 @@ es:
|
||||
orders:
|
||||
edit:
|
||||
order_sure_want_to: ¿Está seguro de que desea %{event} este pedido?
|
||||
voucher_tax_included_in_price: "%{label} (impuestos incluidos en el cupón)"
|
||||
tax_on_fees: "Impuesto sobre las tasas"
|
||||
invoice_email_sent: 'Se ha enviado correo electrónico con la factura.'
|
||||
order_email_resent: 'El correo electrónico del pedido se ha reenviado'
|
||||
@@ -1347,8 +1350,8 @@ es:
|
||||
email_confirmed: "Correo electrónico confirmado"
|
||||
email_not_confirmed: "Correo electrónico no confirmado"
|
||||
vouchers:
|
||||
legend: Bonos
|
||||
voucher_code: Código promocional
|
||||
legend: cupón
|
||||
voucher_code: Código del cupón
|
||||
rate: Impuesto
|
||||
label: Etiqueta
|
||||
purpose: Propósito
|
||||
@@ -1358,7 +1361,7 @@ es:
|
||||
net_value: Valor neto
|
||||
active: ¿Activo?
|
||||
add_new: Añadir nuevo
|
||||
no_voucher_yet: Todavía no hay bonos
|
||||
no_voucher_yet: Todavía no hay cupones
|
||||
white_label:
|
||||
legend: "Etiqueta blanca"
|
||||
hide_ofn_navigation: "Ocultar la navegación de OFN"
|
||||
@@ -1380,6 +1383,8 @@ es:
|
||||
loading: "Cargando"
|
||||
need_to_be_manager: "Sólo los administradores pueden conectar aplicaciones."
|
||||
vine:
|
||||
title: "Voucher Integration Engine (VINE)"
|
||||
tagline: "Permitir el canje de cupones de VINE en tu tienda ."
|
||||
enable: "Conectar"
|
||||
disable: "Desconectar"
|
||||
need_to_be_manager: "Sólo los administradores pueden conectar aplicaciones."
|
||||
@@ -1648,7 +1653,7 @@ es:
|
||||
tag_rules: "Reglas de las Etiquetas"
|
||||
shop_preferences: "Configuración de la tienda"
|
||||
users: "Usuarias"
|
||||
vouchers: Bonos
|
||||
vouchers: Cupones
|
||||
white_label: "Etiqueta blanca"
|
||||
connected_apps: "Aplicaciones connectadas"
|
||||
enterprise_group:
|
||||
@@ -1859,11 +1864,12 @@ es:
|
||||
associated_subscriptions_error: Este horario no se puede eliminar porque tiene suscripciones asociadas
|
||||
vouchers:
|
||||
new:
|
||||
legend: Nuevo bono
|
||||
legend: Nuevo cupón
|
||||
back: Atrás
|
||||
save: Guardar
|
||||
voucher_code: Código promocional
|
||||
voucher_code: Código del cupón
|
||||
voucher_amount: Cantidad
|
||||
voucher_type: Tipo de cupón
|
||||
percentage_rate: Porcentaje (%)
|
||||
controllers:
|
||||
enterprises:
|
||||
@@ -1953,6 +1959,12 @@ es:
|
||||
explaination: Puede revisar y confirmar su pedido en el siguiente paso cual incluye costos finales.
|
||||
submit: Siguiente - Resumen del pedido
|
||||
cancel: Regresar a Su información
|
||||
voucher:
|
||||
voucher: "%{voucher_amount} Cupón"
|
||||
apply_voucher: Utilizar cupón
|
||||
placeholder: Introducir el código del cupón
|
||||
confirm_delete: ¿Está seguro de que desea eliminar este cupón?
|
||||
warning_forfeit_remaining_amount: "Nota: si el total de su pedido es menor que su cupón, es posible que no pueda gastar el valor restante."
|
||||
step3:
|
||||
delivery_details:
|
||||
title: Detalles de entrega
|
||||
@@ -1984,6 +1996,10 @@ es:
|
||||
invalid_email: "Introduce un email válido"
|
||||
select_a_shipping_method: Seleccionar método de envío
|
||||
select_a_payment_method: Seleccionar método de pago
|
||||
voucher_code_blank: Por favor introduzca un código de cupón válido
|
||||
add_voucher_error: Ha habido un error al agregar el cupón
|
||||
create_voucher_error: "Se ha producido un error al crear el cupón: %{error}"
|
||||
voucher_redeeming_error: Se ha producido un error al intentar canjear su cupón
|
||||
shops:
|
||||
hubs:
|
||||
show_closed_shops: "Mostrar tiendas cerradas"
|
||||
@@ -2308,6 +2324,7 @@ es:
|
||||
email_order_summary_subtotal: "Subtotal:"
|
||||
email_order_summary_total: "Total:"
|
||||
email_order_summary_includes_tax: "(incluye impuestos):"
|
||||
email_order_summary_voucher_label: "Cupón ( %{code} ):"
|
||||
email_payment_paid: PAGADO
|
||||
email_payment_not_paid: NO PAGADO
|
||||
email_payment_description: Descripción de pago de la compra
|
||||
@@ -3120,8 +3137,8 @@ es:
|
||||
report_header_transaction_fee: Comisión por transacción (sin impuestos)
|
||||
report_header_total_untaxable_admin: Total de ajustes administrativos no tributables (sin impuestos)
|
||||
report_header_total_taxable_admin: Total de ajustes tributarios de administración (impuestos incluidos)
|
||||
report_header_voucher_label: Etiqueta del bono
|
||||
report_header_voucher_amount: "Cantidad del bono (%{currency_symbol})"
|
||||
report_header_voucher_label: Etiqueta del cupón
|
||||
report_header_voucher_amount: "Cantidad del cupón (%{currency_symbol})"
|
||||
report_line_cost_of_produce: Coste de los productos agrícolas
|
||||
report_header_last_completed_order_date: Fecha del último pedido completado
|
||||
initial_invoice_number: "Número de factura inicial"
|
||||
@@ -3872,7 +3889,7 @@ es:
|
||||
logourl: "URL del logo"
|
||||
are_you_sure_delete: "¿Está seguro de que desea eliminar este registro?"
|
||||
confirm_delete: "Confirmar la eliminación"
|
||||
voucher: "Bono"
|
||||
voucher: "Cupón"
|
||||
configurations: "Configuraciones"
|
||||
general_settings: "Configuración general"
|
||||
site_name: "Nombre del sitio"
|
||||
@@ -3962,6 +3979,7 @@ es:
|
||||
alt_text: "Texto Alternativo"
|
||||
thumbnail: "Miniatura"
|
||||
back_to_images_list: "Volver a lista de imágenes "
|
||||
api_key: "API key"
|
||||
email: Email
|
||||
account_updated: "Cuenta actualizada!"
|
||||
email_updated: "La cuenta se actualizará una vez que se confirme el nuevo correo electrónico."
|
||||
@@ -4270,9 +4288,7 @@ es:
|
||||
providers:
|
||||
provider: "Proveedor"
|
||||
check: "Efectivo / transferencia / etc. (pagos para los que no se requiere validación automática)"
|
||||
pin: "Pin Payments"
|
||||
paypalexpress: "PayPal Express"
|
||||
stripeconnect: "Stripe"
|
||||
stripesca: "Stripe SCA"
|
||||
payments:
|
||||
source_forms:
|
||||
|
||||
@@ -3737,9 +3737,7 @@ es_US:
|
||||
providers:
|
||||
provider: "Proveedor"
|
||||
check: "Efectivo / transferencia / etc. (pagos para los que no se requiere validación automática)"
|
||||
pin: "Pin Payments"
|
||||
paypalexpress: "PayPal Express"
|
||||
stripeconnect: "Stripe"
|
||||
stripesca: "Stripe SCA"
|
||||
payments:
|
||||
source_forms:
|
||||
|
||||
@@ -506,6 +506,7 @@ eu:
|
||||
errors:
|
||||
vine_api: "Errorea gertatu da HJArekiko komunikazioan, saia zaitez geroago."
|
||||
invalid_voucher: "Bonuak ez du balio"
|
||||
expired: "Bonua iraungi da"
|
||||
not_found_voucher: "Sentitzen dugu, ezin izan dugu txartel hori aurkitu, mesedez, egiaztatu kodea."
|
||||
vine_voucher_redeemer_service:
|
||||
errors:
|
||||
@@ -698,6 +699,8 @@ eu:
|
||||
edit:
|
||||
title: "Konektatutako aplikazioaren doikuntzak"
|
||||
enabled_legend: "Gaitutako aplikazio konektatuak"
|
||||
connected_apps_enabled:
|
||||
vine: Voucher Integration Engine (VINE)
|
||||
update:
|
||||
resource: Konektatutako aplikazioaren doikuntzak
|
||||
customers:
|
||||
@@ -1008,6 +1011,7 @@ eu:
|
||||
orders:
|
||||
edit:
|
||||
order_sure_want_to: Ziur al zaude eskaera hau %{event} nahi duzula?
|
||||
voucher_tax_included_in_price: "%{label} (bonuan zerga barne)"
|
||||
tax_on_fees: "Tasen gaineko zerga"
|
||||
invoice_email_sent: 'Posta elektronikoa bidali da fakturarekin.'
|
||||
order_email_resent: 'Eskaeraren posta elektronikoa berriz bidali da'
|
||||
@@ -1302,6 +1306,8 @@ eu:
|
||||
loading: "Kargatzen"
|
||||
need_to_be_manager: "Administratzaileek bakarrik konekta ditzakete aplikazioak."
|
||||
vine:
|
||||
title: "Voucher Integration Engine (VINE)"
|
||||
tagline: "Utzi VINE bonoen trukea zure dendaren erakusleihoan."
|
||||
enable: "Konektatu"
|
||||
disable: "Deskonektatu"
|
||||
need_to_be_manager: "Administratzaileek bakarrik konekta ditzakete aplikazioak."
|
||||
@@ -1784,6 +1790,7 @@ eu:
|
||||
save: Gorde
|
||||
voucher_code: Sustapen-kodea
|
||||
voucher_amount: Kopurua
|
||||
voucher_type: Bonu mota
|
||||
controllers:
|
||||
enterprises:
|
||||
stripe_connect_cancelled: "Striperako konexioa bertan behera geratu da"
|
||||
@@ -1872,6 +1879,12 @@ eu:
|
||||
explaination: Zure eskaera berrikusteko eta berresteko aukera duzu hurrengo urratsean, azken kostuak barne.
|
||||
submit: Hurrengoa - Eskaeraren laburpena
|
||||
cancel: Itzuli Zure informazioa atalera
|
||||
voucher:
|
||||
voucher: "%{voucher_amount} Bonua"
|
||||
apply_voucher: Aplikatu bonoa
|
||||
placeholder: Sartu bonoaren kodea
|
||||
confirm_delete: Ziur zaude bonoa kendu nahi duzula?
|
||||
warning_forfeit_remaining_amount: "Oharra: zure eskaeraren guztizkoa zure bonoa baino txikiagoa bada, baliteke gainerako balioa ezin gastatu ahal izatea."
|
||||
step3:
|
||||
delivery_details:
|
||||
title: Entregaren xehetasunak
|
||||
@@ -1903,7 +1916,10 @@ eu:
|
||||
invalid_email: "Sartu baliozko mezu elektroniko bat"
|
||||
select_a_shipping_method: Hautatu bidalketa-metodoa
|
||||
select_a_payment_method: Hautatu ordainketa-metodoa
|
||||
voucher_code_blank: Mesedez, sartu bono-kode baliodun bat
|
||||
add_voucher_error: Errore bat gertatu da bonoa gehitzean
|
||||
create_voucher_error: "Errore bat gertatu da bonoa sortzerakoan: %{error}"
|
||||
voucher_redeeming_error: Errore bat gertatu da zure bonoa trukatzen saiatzean
|
||||
shops:
|
||||
hubs:
|
||||
show_closed_shops: "Denda itxiak erakutsi"
|
||||
@@ -2227,6 +2243,7 @@ eu:
|
||||
email_order_summary_subtotal: "Subtotala:"
|
||||
email_order_summary_total: "Guztira:"
|
||||
email_order_summary_includes_tax: "(zergak barne):"
|
||||
email_order_summary_voucher_label: "Bonua ( %{code} ):"
|
||||
email_payment_paid: ORDAINDUA
|
||||
email_payment_not_paid: ORDAINDU GABE
|
||||
email_payment_description: Erosketaren ordainketaren deskribapena
|
||||
@@ -4058,9 +4075,7 @@ eu:
|
||||
providers:
|
||||
provider: "Hornitzailea"
|
||||
check: "Eskudirua/transferentzia/etab. (automatikoki baliozkotzea eskatzen ez duten ordainketak)"
|
||||
pin: "Pin Payments"
|
||||
paypalexpress: "PayPal Express"
|
||||
stripeconnect: "Stripe"
|
||||
stripesca: "Stripe SCA"
|
||||
payments:
|
||||
source_forms:
|
||||
|
||||
@@ -18,7 +18,7 @@ fi:
|
||||
phone: "Puhelinnumero"
|
||||
firstname: "Etunimi"
|
||||
lastname: "Sukunimi"
|
||||
zipcode: "Toimituspostinumero"
|
||||
zipcode: "Toimitusosoitteen postinumero"
|
||||
spree/order/bill_address:
|
||||
address1: "Laskutusosoite (Katu ja talonumero)"
|
||||
zipcode: "Laskutuspostinumero"
|
||||
@@ -115,6 +115,67 @@ fi:
|
||||
blank: "ei voi olla tyhjä"
|
||||
too_short: "on liian lyhyt (vähintään %{count} merkkiä)"
|
||||
errors:
|
||||
messages:
|
||||
content_type_invalid:
|
||||
one: "sisältää virheellisen sisältötyypin (valtuutettu sisältötyyppi on %{authorized_human_content_types} )"
|
||||
other: "sisältää virheellisen sisältötyypin (valtuutetut sisältötyypit ovat %{authorized_human_content_types} )"
|
||||
content_type_spoofed:
|
||||
one: "sisältötyyppi ei vastaa sisällöstä havaittua tyyppiä (valtuutettu sisältötyyppi on %{authorized_human_content_types} )"
|
||||
other: "sisältötyyppi ei vastaa sisällöstä havaittua tyyppiä (valtuutetut sisältötyypit ovat %{authorized_human_content_types} )"
|
||||
file_size_not_less_than: "tiedoston koko on oltava pienempi kuin %{max} (nykyinen koko on %{file_size} )"
|
||||
file_size_not_less_than_or_equal_to: "tiedoston koko on oltava pienempi tai yhtä suuri kuin %{max} (nykyinen koko on %{file_size} )"
|
||||
file_size_not_greater_than: "tiedoston koko on oltava suurempi kuin %{min} (nykyinen koko on %{file_size} )"
|
||||
file_size_not_greater_than_or_equal_to: "tiedoston koko on oltava suurempi tai yhtä suuri kuin %{min} (nykyinen koko on %{file_size} )"
|
||||
file_size_not_between: "koko on oltava %{min} ja %{max} välillä (nykyinen koko on %{file_size} )"
|
||||
file_size_not_equal_to: "tiedoston koko on oltava yhtä suuri kuin %{exact} (nykyinen koko on %{file_size} )"
|
||||
total_file_size_not_less_than: "yhteensä tiedoston koko on oltava pienempi kuin %{max} (nykyinen koko on %{total_file_size} )"
|
||||
total_file_size_not_less_than_or_equal_to: "yhteensä tiedoston koko on oltava pienempi tai yhtä suuri kuin %{max} (nykyinen koko on %{total_file_size} )"
|
||||
total_file_size_not_greater_than: "yhteensä tiedoston koko on oltava suurempi kuin %{min} (nykyinen koko on %{total_file_size} )"
|
||||
total_file_size_not_greater_than_or_equal_to: "yhteensä tiedoston koko on oltava suurempi tai yhtä suuri kuin %{min} (nykyinen koko on %{total_file_size} )"
|
||||
total_file_size_not_between: "yhteensä tiedoston koko on oltava %{min} ja %{max} välillä (nykyinen koko on %{total_file_size} )"
|
||||
total_file_size_not_equal_to: "yhteensä tiedoston koko on oltava yhtä suuri kuin %{exact} (nykyinen koko on %{total_file_size} )"
|
||||
duration_not_less_than: "keston on oltava pienempi kuin %{max} (nykyinen kesto on %{duration} )"
|
||||
duration_not_less_than_or_equal_to: "keston on oltava pienempi tai yhtä suuri kuin %{max} (nykyinen kesto on %{duration} )"
|
||||
duration_not_greater_than: "keston on oltava suurempi kuin %{min} (nykyinen kesto on %{duration} )"
|
||||
duration_not_greater_than_or_equal_to: "keston on oltava suurempi tai yhtä suuri kuin %{min} (nykyinen kesto on %{duration} )"
|
||||
duration_not_between: "keston on oltava välillä %{min} ja %{max} (nykyinen kesto on %{duration} )"
|
||||
duration_not_equal_to: "keston on oltava yhtä suuri kuin %{exact} (nykyinen kesto on %{duration} )"
|
||||
limit_out_of_range:
|
||||
zero: "ei liitettyjä tiedostoja (tiedostojen on oltava %{min} ja %{max} välillä)"
|
||||
one: "vain yksi liitetty tiedosto (tiedostojen on oltava %{min} ja %{max} välillä)"
|
||||
other: "Tiedostojen yhteensä on oltava %{min} ja %{max} välillä (liitteenä on %{count} tiedostot)"
|
||||
limit_min_not_reached:
|
||||
zero: "ei liitettyjä tiedostoja (tiedostoissa on oltava vähintään %{min} )"
|
||||
one: "vain yksi tiedosto liitettynä (tiedostojen on oltava vähintään %{min} )"
|
||||
other: "%{count} tiedostot liitteenä (vähintään %{min} tiedostoja on oltava)"
|
||||
limit_max_exceeded:
|
||||
zero: "ei liitettyjä tiedostoja (enintään %{max} tiedostoja)"
|
||||
one: "liian monta tiedostoa liitettynä (suurin sallittu määrä on %{max} , sain tulokseksi %{count} )"
|
||||
other: "liian monta tiedostoa liitettynä (suurin sallittu määrä on %{max} , sain tulokseksi %{count} )"
|
||||
attachment_missing: "puuttuu sen liite"
|
||||
media_metadata_missing: "ei ole kelvollinen mediatiedosto"
|
||||
dimension_min_not_included_in: "on oltava suurempi tai yhtä suuri kuin %{width} x %{height} pikseliä"
|
||||
dimension_max_not_included_in: "on oltava pienempi tai yhtä suuri kuin %{width} x %{height} pikseliä"
|
||||
dimension_width_not_included_in: "Leveys ei sisälly %{min} ja %{max} pikselien väliin"
|
||||
dimension_height_not_included_in: "Korkeutta ei ole %{min} ja %{max} pikselien välillä."
|
||||
dimension_width_not_greater_than_or_equal_to: "leveyden on oltava suurempi tai yhtä suuri kuin %{length} pikseliä"
|
||||
dimension_height_not_greater_than_or_equal_to: "korkeuden on oltava suurempi tai yhtä suuri kuin %{length} pikseliä"
|
||||
dimension_width_not_less_than_or_equal_to: "leveyden on oltava pienempi tai yhtä suuri kuin %{length} pikseliä"
|
||||
dimension_height_not_less_than_or_equal_to: "korkeuden on oltava pienempi tai yhtä suuri kuin %{length} pikseliä"
|
||||
dimension_width_not_equal_to: "leveyden on oltava yhtä suuri kuin %{length} pikseliä"
|
||||
dimension_height_not_equal_to: "korkeuden on oltava yhtä suuri kuin %{length} pikselit"
|
||||
aspect_ratio_not_square: "on oltava neliön muotoinen (nykyinen tiedosto on %{width} x %{height} px)"
|
||||
aspect_ratio_not_portrait: "tiedoston on oltava pystysuuntainen (nykyinen tiedosto on %{width} x %{height} px)"
|
||||
aspect_ratio_not_landscape: "tiedoston on oltava vaakasuuntainen (nykyinen tiedosto on %{width} x %{height} px)"
|
||||
aspect_ratio_not_x_y: "tiedoston on oltava %{authorized_aspect_ratios} (nykyinen tiedosto on %{width} x %{height} px)"
|
||||
aspect_ratio_invalid: "kuvasuhde on virheellinen (kelvolliset kuvasuhteet ovat %{authorized_aspect_ratios} )"
|
||||
file_not_processable: "ei ole tunnistettu kelvolliseksi mediatiedostoksi"
|
||||
pages_not_less_than: "sivumäärän on oltava pienempi kuin %{max} (nykyinen sivumäärä on %{pages} )"
|
||||
pages_not_less_than_or_equal_to: "sivumäärän on oltava pienempi tai yhtä suuri kuin %{max} (nykyinen sivumäärä on %{pages} )"
|
||||
pages_not_greater_than: "sivumäärän on oltava suurempi kuin %{min} (nykyinen sivumäärä on %{pages} )"
|
||||
pages_not_greater_than_or_equal_to: "sivumäärän on oltava suurempi tai yhtä suuri kuin %{min} (nykyinen sivumäärä on %{pages} )"
|
||||
pages_not_between: "sivumäärän on oltava välillä %{min} ja %{max} (nykyinen sivumäärä on %{pages} )"
|
||||
pages_not_equal_to: "sivumäärän on oltava yhtä suuri kuin %{exact} (nykyinen sivumäärä on %{pages} )"
|
||||
not_found:
|
||||
title: "Etsimääsi sivua ei löytynyt (404)"
|
||||
message_html: "<b>Yritä uudelleen</b> <p>Tämä voi olla tilapäinen ongelma. Palaa edelliselle sivulle tai <a href='/'>etusivulle</a> ja yritä uudelleen.</p> <b>Ota yhteyttä tukeen</b> <p>Jos ongelma jatkuu tai on kiireellinen, kerro siitä meille. Löydä yhteystiedot globaalilta <a href='https://openfoodnetwork.org/ofn-local/' target='blank'>Open Food Network Local -sivulta</a>.</p> <p>Autat meitä paljon, jos annat mahdollisimman paljon yksityiskohtia puuttuvasta sivusta.</p>"
|
||||
@@ -185,6 +246,9 @@ fi:
|
||||
disconnect_failure: "Stripe-tilin irrottaminen epäonnistui."
|
||||
success_code:
|
||||
disconnected: "Stripe-tili irrotettu."
|
||||
taler:
|
||||
order_status:
|
||||
claimed: "Maksupyyntö vanheni. Yritä uudelleen."
|
||||
activemodel:
|
||||
errors:
|
||||
messages:
|
||||
@@ -518,6 +582,7 @@ fi:
|
||||
errors:
|
||||
vine_api: "API-yhteydessä tapahtui virhe, yritä myöhemmin uudelleen."
|
||||
invalid_voucher: "Alennuskuponki ei ole kelvollinen"
|
||||
expired: "Kuponki on vanhentunut"
|
||||
not_found_voucher: "Anteeksi, emme löytäneet tätä alennuskuponkia, tarkista koodi."
|
||||
vine_voucher_redeemer_service:
|
||||
errors:
|
||||
@@ -932,6 +997,10 @@ fi:
|
||||
clone:
|
||||
success: Tuote kloonattiin onnistuneesti
|
||||
error: Tuotteen kloonaaminen epäonnistui
|
||||
tag_rules:
|
||||
rules_per_tag:
|
||||
one: "%{tag} llä on 1 sääntö"
|
||||
other: "%{tag} llä on %{count} säännöt."
|
||||
product_import:
|
||||
title: Tuontituotteet
|
||||
file_not_found: Tiedostoa ei löytynyt tai sitä ei voitu avata
|
||||
@@ -1326,6 +1395,9 @@ fi:
|
||||
add_new_button: '+ Lisää uusi oletussääntö'
|
||||
no_tags_yet: Tähän yritykseen ei vielä liity tägejä
|
||||
add_new_tag: '+ Lisää uusi tägi'
|
||||
show_hide_variants: 'Näytä tai Piilota variantit myymälästäni'
|
||||
show_hide_shipping: 'Näytä tai piilota toimitustavat kassalla'
|
||||
show_hide_payment: 'Näytä tai Piilota maksutavat kassalla'
|
||||
show_hide_order_cycles: 'Näytä tai piilota tilausjaksot verkkokaupassani'
|
||||
users:
|
||||
legend: "Käyttäjät"
|
||||
@@ -1479,6 +1551,10 @@ fi:
|
||||
invite_manager:
|
||||
user_already_exists: "Käyttäjä on jo olemassa"
|
||||
error: "Jotain meni pieleen"
|
||||
tag_rules:
|
||||
not_supported_type: tägi -sääntötyyppiä ei tueta
|
||||
confirm_delete: Haluatko varmasti poistaa tämän säännön?
|
||||
destroy_error: tägi -säännön poistamisessa oli ongelma.
|
||||
order_cycles:
|
||||
loading_flash:
|
||||
loading_order_cycles: LADATAAN TILAUSJAKSOJA
|
||||
@@ -1702,6 +1778,8 @@ fi:
|
||||
not_visible: "%{enterprise} ei ole näkyvissä, joten sitä ei löydy kartalta tai hauista"
|
||||
reports:
|
||||
none: ei yhtään
|
||||
metadata:
|
||||
report_title: Ilmianna otsikko
|
||||
deprecated: "Tämä raportti on vanhentunut ja se poistetaan tulevasta julkaisusta."
|
||||
hidden_field: "< Piilotettu >"
|
||||
unitsize: YKSIKKÖKOKO
|
||||
@@ -1804,6 +1882,7 @@ fi:
|
||||
display: Näyttö
|
||||
summary_row: Yhteenvetorivi
|
||||
header_row: Otsikkorivi
|
||||
metadata_rows: Metadata-rivit
|
||||
raw_data: Raakadata
|
||||
formatted_data: Muotoiltu data
|
||||
packing:
|
||||
@@ -2379,8 +2458,15 @@ fi:
|
||||
email_confirmed: "Kiitos sähköpostiosoitteesi vahvistamisesta."
|
||||
email_confirmation_activate_account: "Ennen kuin voimme aktivoida uuden tilisi, meidän on vahvistettava sähköpostiosoitteesi."
|
||||
email_confirmation_greeting: "Hei, %{contact} !"
|
||||
email_confirmation_profile_created: >
|
||||
Profiili käyttäjälle %{name} on luotu onnistuneesti! Profiilisi aktivoimiseksi
|
||||
meidän on vahvistettava tämä sähköpostiosoite.
|
||||
email_confirmation_click_link: "Vahvista sähköpostiosoitteesi ja jatka profiilisi luomista napsauttamalla alla olevaa linkkiä."
|
||||
email_confirmation_link_label: "Vahvista tämä sähköpostiosoite »"
|
||||
email_confirmation_help_html: >
|
||||
Kun olet vahvistanut sähköpostiosoitteesi, voit käyttää ylläpitäjän tiliäsi
|
||||
tässä yrityksessä. Katso %{link} saadaksesi about %{sitename} :n ominaisuuksista
|
||||
ja aloittaaksesi profiilisi tai verkkokauppasi käytön.
|
||||
email_confirmation_notice_unexpected: "Sait tämän viestin, koska rekisteröidyit palvelussa %{sitename} tai joku luultavasti tuntemasi henkilö kutsui sinut rekisteröitymään. Jos et ymmärrä, miksi saat tämän sähköpostin, kirjoita osoitteeseen %{contact} ."
|
||||
email_social: "Ota yhteyttä:"
|
||||
email_contact: "Lähetä meille sähköpostia:"
|
||||
@@ -3276,6 +3362,8 @@ fi:
|
||||
payment_processing_failed: "Payment could not be processed, please check the details you entered"
|
||||
payment_method_not_supported: "Maksutapaa ei tueta. Valitse toinen."
|
||||
payment_updated: "Maksu päivitetty"
|
||||
payment_method_taler:
|
||||
order_summary: "Open Food Network tilaus"
|
||||
cannot_perform_operation: "Maksua ei voitu päivittää"
|
||||
action_required: "Toimenpide vaaditaan"
|
||||
tag_rules: "Tägisäännöt"
|
||||
@@ -3321,6 +3409,7 @@ fi:
|
||||
order_cycles_no_permission_to_coordinate_error: "Yhdelläkään yritykselläsi ei ole lupaa koordinoida tilauskiertoa."
|
||||
order_cycles_no_permission_to_create_error: "Sinulla ei ole oikeutta luoda kyseisen yrityksen koordinoimaa tilausjaksoa."
|
||||
order_cycle_closed: "Valitsemasi tilausjakso on juuri päättynyt. Yritä uudelleen!"
|
||||
order_cycle_closed_next_steps: "Valitsemasi tilausjakso on juuri sulkeutunut. Ota meihin yhteyttä täydentääksesi tilaustasi# %{order_number} !"
|
||||
back_to_orders_list: "Takaisin tilauslistaan"
|
||||
no_orders_found: "Ei tilaukset löytynyt"
|
||||
order_information: "Tilaustiedot"
|
||||
@@ -3888,6 +3977,8 @@ fi:
|
||||
destroy:
|
||||
success: Webhook-päätepiste poistettu onnistuneesti
|
||||
error: Webhook-päätepisteen poistaminen epäonnistui
|
||||
test:
|
||||
success: Joitakin testitietoja lähetetään webhookin URL-osoitteeseen
|
||||
spree:
|
||||
order_updated: "Tilaus päivitetty"
|
||||
cannot_perform_operation: "Tätä toimintoa ei voida suorittaa"
|
||||
@@ -3994,6 +4085,7 @@ fi:
|
||||
logourl: "Logourl"
|
||||
are_you_sure_delete: "Haluatko varmasti poistaa tämän tietueen?"
|
||||
confirm_delete: "Vahvista poisto"
|
||||
tag_rule: "tägi Rule"
|
||||
voucher: "Alennuskuponki"
|
||||
configurations: "Asetukset"
|
||||
general_settings: "Yleiset asetukset"
|
||||
@@ -4085,6 +4177,8 @@ fi:
|
||||
alt_text: "Vaihtoehtoinen teksti"
|
||||
thumbnail: "Pienoiskuva"
|
||||
back_to_images_list: "Takaisin kuvaluetteloon"
|
||||
backend_url: "Taustapalvelun URL-osoite"
|
||||
api_key: "API-avain"
|
||||
email: Sähköposti
|
||||
account_updated: "Tili päivitetty!"
|
||||
email_updated: "Tili päivitetään, kun uusi sähköpostiosoite on vahvistettu."
|
||||
@@ -4401,10 +4495,9 @@ fi:
|
||||
providers:
|
||||
provider: "Palveluntarjoaja"
|
||||
check: "Käteinen/sähköinen maksu/jne. (maksut, joille ei vaadita automaattista vahvistusta)"
|
||||
pin: "PIN-maksut"
|
||||
paypalexpress: "PayPal Express"
|
||||
stripeconnect: "Stripe"
|
||||
stripesca: "Stripe SCA"
|
||||
taler: "Taleri"
|
||||
payments:
|
||||
source_forms:
|
||||
stripe:
|
||||
@@ -4854,13 +4947,31 @@ fi:
|
||||
tag_rule_form:
|
||||
tag_rules:
|
||||
shipping_method_tagged_top: "Toimitustavat merkitty tägillä"
|
||||
shipping_method_tagged_bottom: "ovat:"
|
||||
payment_method_tagged_top: "Maksutavat merkitty tägillä"
|
||||
payment_method_tagged_bottom: "ovat:"
|
||||
order_cycle_tagged_top: "Tilausjaksot merkitty tägillä"
|
||||
order_cycle_tagged_bottom: "ovat:"
|
||||
inventory_tagged_top: "Tägätyt varastomuunnelmat"
|
||||
inventory_tagged_bottom: "ovat:"
|
||||
variant_tagged_top: "Variantit -tunnisteella"
|
||||
variant_tagged_bottom: "ovat:"
|
||||
visible: NÄKYVÄ
|
||||
not_visible: EI NÄKYVÄ
|
||||
tag_rule_group_form:
|
||||
for_customers_tagged: 'Asiakkaille, jotka on tägätty:'
|
||||
add_new_rule: '+ Lisää uusi sääntö'
|
||||
no_rules_yet: Tähän tägiin ei vielä sovelleta sääntöjä
|
||||
add_tag_rule_modal:
|
||||
select_rule_type: "Valitse säännön tyyppi:"
|
||||
add_rule: "lisää sääntö"
|
||||
webhook_endpoint_form:
|
||||
url:
|
||||
create_placeholder: Anna etäwebhook-päätepisteen URL-osoite
|
||||
event_types:
|
||||
order_cycle_opened: Tilausjakso avattu
|
||||
payment_status_changed: Lähetä webhook maksun tilan muutoksesta
|
||||
test_endpoint: Testaa webhookin päätepiste
|
||||
invisible_captcha:
|
||||
sentence_for_humans: "Jätä tyhjäksi"
|
||||
timestamp_error_message: "Yritä uudelleen 5 sekunnin kuluttua."
|
||||
|
||||
@@ -120,6 +120,64 @@ fr:
|
||||
one: "a un contenu invalide (le type de contenu autorisé est %{authorized_human_content_types})"
|
||||
many: "a un contenu invalide (les types de contenus autorisés sont %{authorized_human_content_types})"
|
||||
other: "a un contenu invalide (les types de contenus autorisés sont %{authorized_human_content_types})"
|
||||
content_type_spoofed:
|
||||
one: "a un type de contenu qui n'est pas équivalent avec celui détecté (le type de contenu autorisé est %{authorized_human_content_types})"
|
||||
many: "a un type de contenu qui n'est pas équivalent avec celui détecté (les types de contenus autorisés sont %{authorized_human_content_types})"
|
||||
other: "a un type de contenu qui n'est pas équivalent avec celui détecté (les types de contenus autorisés sont %{authorized_human_content_types})"
|
||||
file_size_not_less_than: "la taille du fichier doit être inférieure à %{max} (la taille actuelle est %{file_size})"
|
||||
file_size_not_less_than_or_equal_to: "la taille du fichier doit être inférieure ou égale à %{max} (la taille actuelle est %{file_size})"
|
||||
file_size_not_greater_than: "la taille du fichier doit être supérieure à %{min} (la taille actuelle est %{file_size})"
|
||||
file_size_not_greater_than_or_equal_to: "la taille du fichier doit être supérieure ou égale à %{min} (la taille actuelle est %{file_size})"
|
||||
file_size_not_between: "la taille du fichier doit être comprise entre %{min} et %{max} (la taille actuelle est %{file_size})"
|
||||
file_size_not_equal_to: "La taille du fichier doit être égale à %{exact} (la taille actuelle est %{file_size} )"
|
||||
total_file_size_not_less_than: "La taille totale du fichier doit être inférieure à %{max} (la taille actuelle est %{total_file_size} )."
|
||||
total_file_size_not_less_than_or_equal_to: "La taille totale du fichier doit être inférieure ou égale à %{max} (la taille actuelle est %{total_file_size} )."
|
||||
total_file_size_not_greater_than: "La taille totale du fichier doit être supérieure à %{min} (la taille actuelle est %{total_file_size} )."
|
||||
total_file_size_not_greater_than_or_equal_to: "La taille totale du fichier doit être supérieure ou égale à %{min} (la taille actuelle est %{total_file_size} )."
|
||||
total_file_size_not_between: "La taille totale du fichier doit être comprise entre %{min} et %{max} (la taille actuelle est %{total_file_size} )."
|
||||
total_file_size_not_equal_to: "La taille totale du fichier doit être égale à %{exact} (la taille actuelle est %{total_file_size} )."
|
||||
duration_not_less_than: "La durée doit être inférieure à %{max} (la durée actuelle est %{duration} )"
|
||||
duration_not_less_than_or_equal_to: "La durée doit être inférieure ou égale à %{max} (la durée actuelle est %{duration})."
|
||||
duration_not_greater_than: "La durée doit être supérieure à %{min} (la durée actuelle est %{duration})"
|
||||
duration_not_greater_than_or_equal_to: "La durée doit être supérieure ou égale à %{min} (la durée actuelle est %{duration})"
|
||||
duration_not_between: "La durée doit être comprise entre %{min} et %{max} (la durée actuelle est %{duration})"
|
||||
duration_not_equal_to: "La durée doit être égale à %{exact} (la durée actuelle est %{duration})"
|
||||
limit_out_of_range:
|
||||
zero: "Aucun fichier joint (doit contenir entre %{min} et %{max} fichiers)"
|
||||
one: "Seulement 1 fichier joint (doit contenir entre %{min} et %{max} fichiers)"
|
||||
other: "Le nombre total de fichiers doit être compris entre %{min} et %{max} (il y a %{count} fichiers joints)."
|
||||
limit_min_not_reached:
|
||||
zero: "Aucun fichier joint (doit contenir au moins %{min} fichiers)"
|
||||
one: "Seulement 1 fichier joint (doit contenir au moins %{min} fichiers)"
|
||||
other: "%{count} fichiers joints (doit contenir au moins %{min} fichiers)"
|
||||
limit_max_exceeded:
|
||||
zero: "Aucun fichier joint (au maximum %{max} fichiers)"
|
||||
one: "Trop de fichiers joints (le maximum est %{max} fichiers, il y en a %{count} )"
|
||||
other: "Trop de fichiers joints (le maximum est %{max} fichiers, il y en a %{count} )"
|
||||
attachment_missing: "une pièce jointe est manquante"
|
||||
media_metadata_missing: "n'est pas un fichier multimédia valide"
|
||||
dimension_min_not_included_in: "doit être plus grand ou égal à %{width} x %{height} pixels"
|
||||
dimension_max_not_included_in: "doit être plus petit ou égal à %{width} x %{height} pixels"
|
||||
dimension_width_not_included_in: "la largeur n'est pas comprise entre %{min} et %{max} pixels"
|
||||
dimension_height_not_included_in: "la hauteur n'est pas comprise entre %{min} et %{max} pixels"
|
||||
dimension_width_not_greater_than_or_equal_to: "la largeur doit être supérieure ou égale à %{length} pixels"
|
||||
dimension_height_not_greater_than_or_equal_to: "la hauteur doit être supérieure ou égale à %{length} pixels"
|
||||
dimension_width_not_less_than_or_equal_to: "la largeur doit être inférieure ou égale à %{length} pixels"
|
||||
dimension_height_not_less_than_or_equal_to: "la hauteur doit être inférieure ou égale à %{length} pixels"
|
||||
dimension_width_not_equal_to: "la largeur doit être égale à %{length} pixels"
|
||||
dimension_height_not_equal_to: "La hauteur doit être égale à %{length} pixels"
|
||||
aspect_ratio_not_square: "doit être carré (le fichier actuel est %{width} x %{height} px)"
|
||||
aspect_ratio_not_portrait: "doit être au format portrait (le fichier actuel mesure %{width} x %{height} px)"
|
||||
aspect_ratio_not_landscape: "doit être au format paysage (le fichier actuel mesure %{width} x %{height} px)"
|
||||
aspect_ratio_not_x_y: "doit être %{authorized_aspect_ratios} (le fichier actuel est %{width} x %{height} px)"
|
||||
aspect_ratio_invalid: "possède un ratio d'image invalide (les ratios d'image valides sont %{authorized_aspect_ratios})"
|
||||
file_not_processable: "n'est pas identifié comme un fichier multimédia valide"
|
||||
pages_not_less_than: "La durée doit être inférieure à %{max} (la durée actuelle est %{pages})"
|
||||
pages_not_less_than_or_equal_to: "La durée doit être inférieure ou égale à %{max} (la durée actuelle est %{pages})"
|
||||
pages_not_greater_than: "La durée doit être supérieure à %{max} (la durée actuelle est %{pages})"
|
||||
pages_not_greater_than_or_equal_to: "La durée doit être supérieure ou égale à %{min} (la durée actuelle est %{pages})"
|
||||
pages_not_between: "La durée doit être comprise entre %{min} et %{max} (la durée actuelle est %{pages})"
|
||||
pages_not_equal_to: "La durée doit être égale à %{exact} (la durée actuelle est %{pages})"
|
||||
not_found:
|
||||
title: "La page que vous recherchez n'existe pas (erreur 404)"
|
||||
message_html: "<b> Veuillez essayer à nouveau </b> <p> Il s'agit peut-être d'un problème temporaire. Veuillez cliquer sur le bouton retour de votre navigateur ou retourner à l' <a href='/'> Accueil </a> et recommencez. </p> <b> Contacter notre support </b> <p> Si le problème persiste ou si c'est urgent, veuillez nous contacter. </p>"
|
||||
@@ -190,6 +248,9 @@ fr:
|
||||
disconnect_failure: "Déconnecter Stripe a échoué."
|
||||
success_code:
|
||||
disconnected: "Le compte Stripe est déconnecté."
|
||||
taler:
|
||||
order_status:
|
||||
claimed: "La demande de paiement a expiré. Merci d'essayer à nouveau."
|
||||
activemodel:
|
||||
errors:
|
||||
messages:
|
||||
@@ -524,6 +585,7 @@ fr:
|
||||
errors:
|
||||
vine_api: "Il y a eu une erreur de communication avec l'API, merci de réessayer."
|
||||
invalid_voucher: "Le bon de réduction n'est pas valide."
|
||||
expired: "Le bon de réduction a expiré."
|
||||
not_found_voucher: "Désolé, nous n'avons pas trouvé ce bon de réduction. Merci de vérifier le code qui vous a été transmis."
|
||||
vine_voucher_redeemer_service:
|
||||
errors:
|
||||
@@ -1442,6 +1504,7 @@ fr:
|
||||
owner: Gestionnaire principal
|
||||
producer: Producteur
|
||||
sells_options:
|
||||
unspecified: non spécifié
|
||||
none: aucun
|
||||
own: les miens
|
||||
any: tous
|
||||
@@ -2882,7 +2945,7 @@ fr:
|
||||
shipping_method_destroy_error: "Cette méthode de livraison ne peut pas être supprimée car elle est référencée dans une commande : %{number}."
|
||||
fees: "Frais"
|
||||
fee_name: "Nom de la marge/commission"
|
||||
fee_owner: "Propriétaire des droits"
|
||||
fee_owner: "Propriétaire de la marge/commission"
|
||||
item_cost: "Coût du produit"
|
||||
bulk: "Vrac"
|
||||
shop_variant_quantity_min: "min"
|
||||
@@ -3307,6 +3370,8 @@ fr:
|
||||
payment_processing_failed: "Le paiement n'a pas pu être traité, veuillez vérifier les informations saisies"
|
||||
payment_method_not_supported: "Cette méthode de paiement n'est pas maintenue. Veuillez en sélectionner une autre."
|
||||
payment_updated: "Paiement mis à jour"
|
||||
payment_method_taler:
|
||||
order_summary: "Commande CoopCircuits"
|
||||
cannot_perform_operation: "Le paiement n'a pas pu être mis à jour."
|
||||
action_required: "Une action est requise"
|
||||
tag_rules: "Règles de tag"
|
||||
@@ -3983,6 +4048,8 @@ fr:
|
||||
destroy:
|
||||
success: Le webhook a bien été supprimé.
|
||||
error: Le webhook n'a pas pu être supprimé.
|
||||
test:
|
||||
success: Des données test vont être envoyées à l'URL du webhook
|
||||
spree:
|
||||
order_updated: "La commande a été mise à jour"
|
||||
cannot_perform_operation: "Cette opération ne peut pas être réalisée"
|
||||
@@ -4089,6 +4156,7 @@ fr:
|
||||
logourl: "URL logo"
|
||||
are_you_sure_delete: "Etes-vous certain de vouloir supprimer cet élément ?"
|
||||
confirm_delete: "Confirmer la suppression"
|
||||
tag_rule: "Règle de tag"
|
||||
voucher: "Bon de réduction"
|
||||
configurations: "Configurations"
|
||||
general_settings: "Configurations générales"
|
||||
@@ -4180,6 +4248,8 @@ fr:
|
||||
alt_text: "Texte alternatif"
|
||||
thumbnail: "Miniature"
|
||||
back_to_images_list: "Retour à la liste des images"
|
||||
backend_url: "URL du backend"
|
||||
api_key: "Clé API"
|
||||
email: Email
|
||||
account_updated: "Compte mis à jour!"
|
||||
email_updated: "Le compte sera mis à jour une fois la nouvelle adresse email confirmée."
|
||||
@@ -4496,10 +4566,9 @@ fr:
|
||||
providers:
|
||||
provider: "Fournisseur"
|
||||
check: "Espèces / chèques / virements / autres "
|
||||
pin: "Méthode de paiement réservée à l'Australie (Pin Payments)"
|
||||
paypalexpress: "PayPal Express"
|
||||
stripeconnect: "Stripe (ancienne version)"
|
||||
stripesca: "Stripe"
|
||||
taler: "Taler"
|
||||
payments:
|
||||
source_forms:
|
||||
stripe:
|
||||
@@ -4986,6 +5055,8 @@ fr:
|
||||
create_placeholder: Entrez l'URL du point de terminaison du webhook
|
||||
event_types:
|
||||
order_cycle_opened: Cycle de vente ouvert
|
||||
payment_status_changed: Poster webhook sur le changement du statut de paiement
|
||||
test_endpoint: Tester le point de terminaison du webhook
|
||||
invisible_captcha:
|
||||
sentence_for_humans: "Merci de laisser ce champ libre"
|
||||
timestamp_error_message: "S'il vous plaît réessayez après 5 secondes."
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user