mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-12 18:36:49 +00:00
Compare commits
188 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90288b8cbf | ||
|
|
c821b0a285 | ||
|
|
c37376d67e | ||
|
|
49ec5b2089 | ||
|
|
92ef5fe3d5 | ||
|
|
ae477b7e52 | ||
|
|
0e191e5fca | ||
|
|
64f9ea6fc0 | ||
|
|
058c6749da | ||
|
|
2d15ec4458 | ||
|
|
56eaa8bb98 | ||
|
|
1e1f1e1e1b | ||
|
|
1f8a9f9c76 | ||
|
|
b1893942ac | ||
|
|
ad59ed4d40 | ||
|
|
8491a167ed | ||
|
|
59277292fb | ||
|
|
354a7ab687 | ||
|
|
a5a1ee9bd9 | ||
|
|
ad3f78ef69 | ||
|
|
e02497b163 | ||
|
|
7d2d94398f | ||
|
|
0ecf004ff2 | ||
|
|
444f448207 | ||
|
|
d9381b23d7 | ||
|
|
6a9a2884d6 | ||
|
|
70edd4b898 | ||
|
|
b57a2befd9 | ||
|
|
fef9a78198 | ||
|
|
dd86736170 | ||
|
|
0d8c7ef118 | ||
|
|
20730b8768 | ||
|
|
ad7c69189b | ||
|
|
3a72aefc1c | ||
|
|
e855ea0dbd | ||
|
|
1eba950e19 | ||
|
|
9cd04c087e | ||
|
|
459d25e533 | ||
|
|
b06e562425 | ||
|
|
2936cfebca | ||
|
|
b8ad428b5d | ||
|
|
ca34d24847 | ||
|
|
6e581fce75 | ||
|
|
66041061fb | ||
|
|
e54c27c900 | ||
|
|
b3d3d6bf06 | ||
|
|
5876c52318 | ||
|
|
842f4ae40e | ||
|
|
342ef4e9eb | ||
|
|
210201514e | ||
|
|
2d3f18a71b | ||
|
|
9d284b7110 | ||
|
|
994f1ca6c6 | ||
|
|
f65e4797cf | ||
|
|
52aeec5ac4 | ||
|
|
7032b3f463 | ||
|
|
c26686b430 | ||
|
|
60c8f4ee20 | ||
|
|
25f396c126 | ||
|
|
0166abcd2a | ||
|
|
4cd0071dd4 | ||
|
|
32c96b72ad | ||
|
|
30701d61e2 | ||
|
|
45b712ddcd | ||
|
|
3153e99497 | ||
|
|
a2f263e081 | ||
|
|
3cb6a2617b | ||
|
|
420deca437 | ||
|
|
76aebf8a72 | ||
|
|
1ec570375f | ||
|
|
75c33b29d5 | ||
|
|
1bfff91c72 | ||
|
|
d469552afc | ||
|
|
e6cffde8fb | ||
|
|
910ded1a8c | ||
|
|
2555a9e710 | ||
|
|
f532c4712e | ||
|
|
3af28c4b5b | ||
|
|
63b864253d | ||
|
|
8efeec4301 | ||
|
|
bed33928e0 | ||
|
|
bb7a31b286 | ||
|
|
75b2fe1dd4 | ||
|
|
c0924fbe5e | ||
|
|
d72bc49409 | ||
|
|
06867ff7ea | ||
|
|
76a1fe7767 | ||
|
|
3363c523ea | ||
|
|
91628f8daa | ||
|
|
f3dfbab109 | ||
|
|
d01474ebcd | ||
|
|
a062a7b697 | ||
|
|
fe8b805e1f | ||
|
|
f3f43225cb | ||
|
|
65604f5b04 | ||
|
|
661bb29029 | ||
|
|
b725697972 | ||
|
|
b8546db1e5 | ||
|
|
bc25a5ecd6 | ||
|
|
71de96e0a6 | ||
|
|
23bcdc1cb7 | ||
|
|
60ac1c9fbe | ||
|
|
fcd4d073c4 | ||
|
|
df4cf4b768 | ||
|
|
3f39d94bd3 | ||
|
|
acfe3f6589 | ||
|
|
1717c5376b | ||
|
|
1426b6eeb7 | ||
|
|
188b2eb754 | ||
|
|
6e055ddbdf | ||
|
|
025fc784a8 | ||
|
|
fefd0239e6 | ||
|
|
0fa67c69fd | ||
|
|
44cbe55c96 | ||
|
|
56d3ac247d | ||
|
|
0ed08f8f9d | ||
|
|
667b49b7f1 | ||
|
|
dd6d1ea64b | ||
|
|
f0dd1885c9 | ||
|
|
05b6200c8f | ||
|
|
fcd6897240 | ||
|
|
c23c773942 | ||
|
|
7af960fceb | ||
|
|
45a0705379 | ||
|
|
6da1200b64 | ||
|
|
1cf31f4028 | ||
|
|
6df71f28ca | ||
|
|
9272d6d82f | ||
|
|
a8114e42a7 | ||
|
|
17e02e7304 | ||
|
|
6ba80f57b3 | ||
|
|
d90200fb3f | ||
|
|
08114b495a | ||
|
|
7b6b3d907c | ||
|
|
cf9ffd8931 | ||
|
|
e6b9373570 | ||
|
|
ec44947b37 | ||
|
|
c0639b37bb | ||
|
|
38388be4da | ||
|
|
352f1ba900 | ||
|
|
7a0ecc777a | ||
|
|
aeefe841bf | ||
|
|
70757ccdef | ||
|
|
7450f8a530 | ||
|
|
618d597f6d | ||
|
|
b7f969eed9 | ||
|
|
b28e30cb6c | ||
|
|
681eee9309 | ||
|
|
6937a133ae | ||
|
|
ddc45e1cd8 | ||
|
|
28a11f1fee | ||
|
|
1c4febd332 | ||
|
|
9e1de75db6 | ||
|
|
8829f6ad03 | ||
|
|
6212cd4d07 | ||
|
|
29a24b7305 | ||
|
|
7c31c951a1 | ||
|
|
33bac6f816 | ||
|
|
a6f0a36b6d | ||
|
|
b253950075 | ||
|
|
b19b987ed0 | ||
|
|
dc84d32028 | ||
|
|
82c99891eb | ||
|
|
f30b899569 | ||
|
|
cd8b7cd239 | ||
|
|
d80481a106 | ||
|
|
174be39c5e | ||
|
|
5f694276f1 | ||
|
|
affb5d7281 | ||
|
|
87b9eeb2f1 | ||
|
|
81c75b2b71 | ||
|
|
ec6d490676 | ||
|
|
838e88a502 | ||
|
|
4b19d38c58 | ||
|
|
7725fae992 | ||
|
|
b43fa55a7b | ||
|
|
d5c79be7d9 | ||
|
|
1b9d64ad5e | ||
|
|
c648249160 | ||
|
|
765ce68c11 | ||
|
|
020d90b957 | ||
|
|
8d407b1dc9 | ||
|
|
fe1b8aaab3 | ||
|
|
ade35f2fa2 | ||
|
|
cd01a27bdd | ||
|
|
2f9c856645 | ||
|
|
8e8878e43a | ||
|
|
a37e08c2fd |
3
.github/workflows/build.yml
vendored
3
.github/workflows/build.yml
vendored
@@ -410,5 +410,6 @@ jobs:
|
||||
include-hidden-files: true
|
||||
- name: Compare SimpleCov results with Undercover
|
||||
run: |
|
||||
git fetch --no-tags origin master:master
|
||||
git fetch --no-tags origin ${{ github.event.pull_request.base.ref }}:master
|
||||
bundle exec undercover
|
||||
if: ${{ github.ref != 'refs/heads/master' }} # Does not run on master, as we can't fetch master in the master branch
|
||||
|
||||
@@ -16,6 +16,7 @@ AllCops:
|
||||
- node_modules/**/*
|
||||
# Excluding: inadequate Naming/FileName rule rejects GemFile name with camelcase
|
||||
- engines/web/Gemfile
|
||||
- .undercover
|
||||
|
||||
Bundler/DuplicatedGem:
|
||||
Enabled: false
|
||||
|
||||
@@ -98,6 +98,7 @@ Metrics/ClassLength:
|
||||
- 'lib/reporting/reports/enterprise_fee_summary/enterprise_fees_with_tax_report_by_producer.rb'
|
||||
- 'lib/reporting/reports/enterprise_fee_summary/scope.rb'
|
||||
- 'lib/reporting/reports/xero_invoices/base.rb'
|
||||
- 'app/services/permissions/order.rb'
|
||||
|
||||
# Offense count: 30
|
||||
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
||||
|
||||
@@ -4,17 +4,8 @@
|
||||
SimpleCov.start 'rails' do
|
||||
add_filter '/bin/'
|
||||
add_filter '/config/'
|
||||
add_filter '/jobs/application_job.rb'
|
||||
add_filter '/schemas/'
|
||||
add_filter '/lib/generators'
|
||||
add_filter '/spec/'
|
||||
add_filter '/vendor/'
|
||||
add_filter '/public'
|
||||
add_filter '/swagger'
|
||||
add_filter '/script'
|
||||
add_filter '/log'
|
||||
add_filter '/db'
|
||||
add_filter '/lib/tasks/sample_data/'
|
||||
|
||||
formatter SimpleCov::Formatter::SimpleFormatter
|
||||
end
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#!/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
-l coverage/lcov/openfoodnetwork.lcov
|
||||
-c master
|
||||
-c master
|
||||
|
||||
3
Gemfile
3
Gemfile
@@ -152,6 +152,7 @@ end
|
||||
group :test, :development do
|
||||
gem 'bullet'
|
||||
gem 'capybara'
|
||||
gem 'capybara-shadowdom'
|
||||
gem 'cuprite'
|
||||
gem 'database_cleaner', require: false
|
||||
gem 'debug', '>= 1.0.0'
|
||||
@@ -171,9 +172,9 @@ end
|
||||
|
||||
group :test do
|
||||
gem 'pdf-reader'
|
||||
gem 'puffing-billy'
|
||||
gem 'rails-controller-testing'
|
||||
gem 'simplecov', require: false
|
||||
gem 'simplecov-lcov', require: false
|
||||
gem 'undercover', require: false
|
||||
gem 'vcr', require: false
|
||||
gem 'webmock', require: false
|
||||
|
||||
250
Gemfile.lock
250
Gemfile.lock
@@ -48,54 +48,58 @@ PATH
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
Ascii85 (1.1.0)
|
||||
actioncable (7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
Ascii85 (2.0.1)
|
||||
actioncable (7.1.5.2)
|
||||
actionpack (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
actionmailbox (7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
activejob (= 7.0.8)
|
||||
activerecord (= 7.0.8)
|
||||
activestorage (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
zeitwerk (~> 2.6)
|
||||
actionmailbox (7.1.5.2)
|
||||
actionpack (= 7.1.5.2)
|
||||
activejob (= 7.1.5.2)
|
||||
activerecord (= 7.1.5.2)
|
||||
activestorage (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
mail (>= 2.7.1)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
actionmailer (7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
actionview (= 7.0.8)
|
||||
activejob (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
actionmailer (7.1.5.2)
|
||||
actionpack (= 7.1.5.2)
|
||||
actionview (= 7.1.5.2)
|
||||
activejob (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (7.0.8)
|
||||
actionview (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
rack (~> 2.0, >= 2.2.4)
|
||||
rails-dom-testing (~> 2.2)
|
||||
actionpack (7.1.5.2)
|
||||
actionview (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
nokogiri (>= 1.8.5)
|
||||
racc
|
||||
rack (>= 2.2.4)
|
||||
rack-session (>= 1.0.1)
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||
rails-dom-testing (~> 2.2)
|
||||
rails-html-sanitizer (~> 1.6)
|
||||
actionpack-action_caching (1.2.2)
|
||||
actionpack (>= 4.0.0)
|
||||
actiontext (7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
activerecord (= 7.0.8)
|
||||
activestorage (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
actiontext (7.1.5.2)
|
||||
actionpack (= 7.1.5.2)
|
||||
activerecord (= 7.1.5.2)
|
||||
activestorage (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
globalid (>= 0.6.0)
|
||||
nokogiri (>= 1.8.5)
|
||||
actionview (7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
actionview (7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
||||
erubi (~> 1.11)
|
||||
rails-dom-testing (~> 2.2)
|
||||
rails-html-sanitizer (~> 1.6)
|
||||
active_model_serializers (0.8.4)
|
||||
activemodel (>= 3.0)
|
||||
active_storage_validations (1.1.4)
|
||||
@@ -103,8 +107,8 @@ GEM
|
||||
activemodel (>= 5.2.0)
|
||||
activestorage (>= 5.2.0)
|
||||
activesupport (>= 5.2.0)
|
||||
activejob (7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
activejob (7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
globalid (>= 0.3.6)
|
||||
activemerchant (1.133.0)
|
||||
activesupport (>= 4.2)
|
||||
@@ -112,11 +116,12 @@ GEM
|
||||
i18n (>= 0.6.9)
|
||||
nokogiri (~> 1.4)
|
||||
rexml (~> 3.2.5)
|
||||
activemodel (7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
activerecord (7.0.8)
|
||||
activemodel (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
activemodel (7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
activerecord (7.1.5.2)
|
||||
activemodel (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
timeout (>= 0.4.0)
|
||||
activerecord-import (1.6.0)
|
||||
activerecord (>= 4.2)
|
||||
activerecord-postgresql-adapter (0.0.1)
|
||||
@@ -128,17 +133,24 @@ GEM
|
||||
multi_json (~> 1.11, >= 1.11.2)
|
||||
rack (>= 2.0.8, < 4)
|
||||
railties (>= 6.1)
|
||||
activestorage (7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
activejob (= 7.0.8)
|
||||
activerecord (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
activestorage (7.1.5.2)
|
||||
actionpack (= 7.1.5.2)
|
||||
activejob (= 7.1.5.2)
|
||||
activerecord (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
marcel (~> 1.0)
|
||||
mini_mime (>= 1.1.0)
|
||||
activesupport (7.0.8)
|
||||
activesupport (7.1.5.2)
|
||||
base64
|
||||
benchmark (>= 0.3)
|
||||
bigdecimal
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
connection_pool (>= 2.2.5)
|
||||
drb
|
||||
i18n (>= 1.6, < 2)
|
||||
logger (>= 1.4.2)
|
||||
minitest (>= 5.1)
|
||||
mutex_m
|
||||
securerandom (>= 0.3)
|
||||
tzinfo (~> 2.0)
|
||||
acts-as-taggable-on (10.0.0)
|
||||
activerecord (>= 6.1, < 7.2)
|
||||
@@ -159,7 +171,7 @@ GEM
|
||||
angularjs-rails (1.8.0)
|
||||
arel-helpers (2.14.0)
|
||||
activerecord (>= 3.1.0, < 8)
|
||||
ast (2.4.2)
|
||||
ast (2.4.3)
|
||||
attr_required (1.0.2)
|
||||
aws-eventstream (1.3.0)
|
||||
aws-partitions (1.929.0)
|
||||
@@ -177,10 +189,11 @@ GEM
|
||||
aws-sigv4 (~> 1.8)
|
||||
aws-sigv4 (1.8.0)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
base64 (0.2.0)
|
||||
base64 (0.3.0)
|
||||
bcp47_spec (0.2.1)
|
||||
bcrypt (3.1.20)
|
||||
bigdecimal (3.1.8)
|
||||
benchmark (0.4.1)
|
||||
bigdecimal (3.2.2)
|
||||
bindata (2.5.0)
|
||||
bindex (0.8.1)
|
||||
bootsnap (1.18.3)
|
||||
@@ -188,7 +201,7 @@ GEM
|
||||
bugsnag (6.26.4)
|
||||
concurrent-ruby (~> 1.0)
|
||||
builder (3.2.4)
|
||||
bullet (7.1.6)
|
||||
bullet (8.0.8)
|
||||
activesupport (>= 3.0.0)
|
||||
uniform_notifier (~> 1.11)
|
||||
cable_ready (5.0.6)
|
||||
@@ -208,12 +221,14 @@ GEM
|
||||
rack-test (>= 0.6.3)
|
||||
regexp_parser (>= 1.5, < 3.0)
|
||||
xpath (~> 3.2)
|
||||
capybara-shadowdom (0.3.0)
|
||||
capybara
|
||||
caxlsx (3.3.0)
|
||||
htmlentities (~> 4.3, >= 4.3.4)
|
||||
marcel (~> 1.0)
|
||||
nokogiri (~> 1.10, >= 1.10.4)
|
||||
rubyzip (>= 1.3.0, < 3)
|
||||
cgi (0.3.6)
|
||||
cgi (0.3.7)
|
||||
childprocess (5.0.0)
|
||||
choice (0.2.0)
|
||||
chronic (0.10.2)
|
||||
@@ -228,8 +243,9 @@ GEM
|
||||
combine_pdf (1.0.26)
|
||||
matrix
|
||||
ruby-rc4 (>= 0.1.5)
|
||||
concurrent-ruby (1.3.1)
|
||||
connection_pool (2.4.1)
|
||||
concurrent-ruby (1.3.5)
|
||||
connection_pool (2.5.3)
|
||||
cookiejar (0.3.4)
|
||||
crack (1.0.0)
|
||||
bigdecimal
|
||||
rexml
|
||||
@@ -248,7 +264,7 @@ GEM
|
||||
database_cleaner-core (2.0.1)
|
||||
datafoodconsortium-connector (1.1.0)
|
||||
virtual_assembly-semantizer (~> 1.0, >= 1.0.5)
|
||||
date (3.3.4)
|
||||
date (3.4.1)
|
||||
debug (1.9.2)
|
||||
irb (~> 1.10)
|
||||
reline (>= 0.3.8)
|
||||
@@ -269,11 +285,25 @@ GEM
|
||||
digest (3.1.1)
|
||||
docile (1.4.0)
|
||||
dotenv (3.1.2)
|
||||
drb (2.2.3)
|
||||
em-http-request (1.1.7)
|
||||
addressable (>= 2.3.4)
|
||||
cookiejar (!= 0.3.1)
|
||||
em-socksify (>= 0.3)
|
||||
eventmachine (>= 1.0.3)
|
||||
http_parser.rb (>= 0.6.0)
|
||||
em-socksify (0.3.3)
|
||||
base64
|
||||
eventmachine (>= 1.0.0.beta.4)
|
||||
em-synchrony (1.0.6)
|
||||
eventmachine (>= 1.0.0.beta.1)
|
||||
email_validator (2.2.4)
|
||||
activemodel
|
||||
erubi (1.12.0)
|
||||
et-orbi (1.2.7)
|
||||
et-orbi (1.3.0)
|
||||
tzinfo
|
||||
eventmachine (1.2.7)
|
||||
eventmachine_httpserver (0.2.1)
|
||||
excon (0.81.0)
|
||||
execjs (2.7.0)
|
||||
factory_bot (6.2.0)
|
||||
@@ -323,8 +353,8 @@ GEM
|
||||
nokogiri (>= 1.5.11, < 2.0.0)
|
||||
foreman (0.88.1)
|
||||
formatador (0.2.5)
|
||||
fugit (1.8.1)
|
||||
et-orbi (~> 1, >= 1.2.7)
|
||||
fugit (1.11.1)
|
||||
et-orbi (~> 1, >= 1.2.11)
|
||||
raabro (~> 1.4)
|
||||
fuubar (2.5.1)
|
||||
rspec-core (~> 3.0)
|
||||
@@ -347,6 +377,7 @@ GEM
|
||||
hashie (5.0.0)
|
||||
highline (2.0.3)
|
||||
htmlentities (4.3.4)
|
||||
http_parser.rb (0.8.0)
|
||||
i18n (1.14.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
i18n-js (3.9.2)
|
||||
@@ -420,7 +451,8 @@ GEM
|
||||
listen (3.9.0)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
loofah (2.22.0)
|
||||
logger (1.7.0)
|
||||
loofah (2.24.1)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.12.0)
|
||||
mail (2.8.1)
|
||||
@@ -440,7 +472,7 @@ GEM
|
||||
mini_magick (4.11.0)
|
||||
mini_mime (1.1.5)
|
||||
mini_portile2 (2.8.6)
|
||||
minitest (5.23.1)
|
||||
minitest (5.25.5)
|
||||
monetize (1.13.0)
|
||||
money (~> 6.12)
|
||||
money (6.16.0)
|
||||
@@ -448,9 +480,10 @@ GEM
|
||||
msgpack (1.7.2)
|
||||
multi_json (1.15.0)
|
||||
multi_xml (0.6.0)
|
||||
mutex_m (0.3.0)
|
||||
net-http (0.4.1)
|
||||
uri
|
||||
net-imap (0.4.10)
|
||||
net-imap (0.4.20)
|
||||
date
|
||||
net-protocol
|
||||
net-pop (0.1.2)
|
||||
@@ -461,7 +494,7 @@ GEM
|
||||
net-protocol
|
||||
newrelic_rpm (9.9.0)
|
||||
nio4r (2.7.1)
|
||||
nokogiri (1.16.5)
|
||||
nokogiri (1.18.9)
|
||||
mini_portile2 (~> 2.8.2)
|
||||
racc (~> 1.4)
|
||||
nokogiri-html5-inference (0.3.0)
|
||||
@@ -505,7 +538,7 @@ GEM
|
||||
parallel (1.24.0)
|
||||
paranoia (2.6.3)
|
||||
activerecord (>= 5.1, < 7.2)
|
||||
parser (3.3.2.0)
|
||||
parser (3.3.8.0)
|
||||
ast (~> 2.4.1)
|
||||
racc
|
||||
paypal-sdk-core (0.3.4)
|
||||
@@ -513,9 +546,9 @@ GEM
|
||||
xml-simple
|
||||
paypal-sdk-merchant (1.117.2)
|
||||
paypal-sdk-core (~> 0.3.0)
|
||||
pdf-reader (2.12.0)
|
||||
Ascii85 (~> 1.0)
|
||||
afm (~> 0.2.1)
|
||||
pdf-reader (2.15.0)
|
||||
Ascii85 (>= 1.0, < 3.0, != 2.0.0)
|
||||
afm (>= 0.2.1, < 2)
|
||||
hashery (~> 2.0)
|
||||
ruby-rc4
|
||||
ttfunk
|
||||
@@ -527,14 +560,22 @@ GEM
|
||||
psych (5.1.2)
|
||||
stringio
|
||||
public_suffix (5.0.5)
|
||||
puffing-billy (4.0.2)
|
||||
addressable (~> 2.5)
|
||||
em-http-request (~> 1.1, >= 1.1.0)
|
||||
em-synchrony
|
||||
eventmachine (~> 1.2)
|
||||
eventmachine_httpserver
|
||||
http_parser.rb (~> 0.8.0)
|
||||
multi_json
|
||||
puma (6.5.0)
|
||||
nio4r (~> 2.0)
|
||||
query_count (1.1.1)
|
||||
activerecord (>= 4.2)
|
||||
railties (>= 4.2)
|
||||
raabro (1.4.0)
|
||||
racc (1.8.0)
|
||||
rack (2.2.11)
|
||||
racc (1.8.1)
|
||||
rack (2.2.14)
|
||||
rack-mini-profiler (2.3.4)
|
||||
rack (>= 1.2.0)
|
||||
rack-oauth2 (2.2.1)
|
||||
@@ -555,20 +596,23 @@ GEM
|
||||
rack-test (2.1.0)
|
||||
rack (>= 1.3)
|
||||
rack-timeout (0.7.0)
|
||||
rails (7.0.8)
|
||||
actioncable (= 7.0.8)
|
||||
actionmailbox (= 7.0.8)
|
||||
actionmailer (= 7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
actiontext (= 7.0.8)
|
||||
actionview (= 7.0.8)
|
||||
activejob (= 7.0.8)
|
||||
activemodel (= 7.0.8)
|
||||
activerecord (= 7.0.8)
|
||||
activestorage (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
rackup (1.0.1)
|
||||
rack (< 3)
|
||||
webrick
|
||||
rails (7.1.5.2)
|
||||
actioncable (= 7.1.5.2)
|
||||
actionmailbox (= 7.1.5.2)
|
||||
actionmailer (= 7.1.5.2)
|
||||
actionpack (= 7.1.5.2)
|
||||
actiontext (= 7.1.5.2)
|
||||
actionview (= 7.1.5.2)
|
||||
activejob (= 7.1.5.2)
|
||||
activemodel (= 7.1.5.2)
|
||||
activerecord (= 7.1.5.2)
|
||||
activestorage (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
bundler (>= 1.15.0)
|
||||
railties (= 7.0.8)
|
||||
railties (= 7.1.5.2)
|
||||
rails-controller-testing (1.0.5)
|
||||
actionpack (>= 5.0.1.rc1)
|
||||
actionview (>= 5.0.1.rc1)
|
||||
@@ -582,20 +626,21 @@ GEM
|
||||
activesupport (>= 4.2)
|
||||
choice (~> 0.2.0)
|
||||
ruby-graphviz (~> 1.2)
|
||||
rails-html-sanitizer (1.6.0)
|
||||
rails-html-sanitizer (1.6.1)
|
||||
loofah (~> 2.21)
|
||||
nokogiri (~> 1.14)
|
||||
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
|
||||
rails-i18n (7.0.9)
|
||||
i18n (>= 0.7, < 2)
|
||||
railties (>= 6.0.0, < 8)
|
||||
rails_safe_tasks (1.0.0)
|
||||
railties (7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
method_source
|
||||
railties (7.1.5.2)
|
||||
actionpack (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
irb
|
||||
rackup (>= 1.0.0)
|
||||
rake (>= 12.2)
|
||||
thor (~> 1.0)
|
||||
zeitwerk (~> 2.5)
|
||||
thor (~> 1.0, >= 1.2.2)
|
||||
zeitwerk (~> 2.6)
|
||||
rainbow (3.1.1)
|
||||
rake (13.2.1)
|
||||
ransack (4.1.1)
|
||||
@@ -717,7 +762,7 @@ GEM
|
||||
rubyzip (2.3.2)
|
||||
rufus-scheduler (3.8.2)
|
||||
fugit (~> 1.1, >= 1.1.6)
|
||||
rugged (1.7.2)
|
||||
rugged (1.9.0)
|
||||
sanitize (6.1.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.12.0)
|
||||
@@ -729,6 +774,7 @@ GEM
|
||||
sprockets-rails (>= 2.0, < 4.0)
|
||||
tilt (>= 1.1, < 3)
|
||||
sd_notify (0.1.1)
|
||||
securerandom (0.4.1)
|
||||
semantic_range (3.0.0)
|
||||
shoulda-matchers (6.2.0)
|
||||
activesupport (>= 5.2.0)
|
||||
@@ -746,7 +792,6 @@ GEM
|
||||
simplecov-html (~> 0.11)
|
||||
simplecov_json_formatter (~> 0.1)
|
||||
simplecov-html (0.12.3)
|
||||
simplecov-lcov (0.8.0)
|
||||
simplecov_json_formatter (0.1.4)
|
||||
spreadsheet_architect (5.0.0)
|
||||
caxlsx (>= 3.3.0, < 4)
|
||||
@@ -794,12 +839,13 @@ GEM
|
||||
temple (0.8.2)
|
||||
terminal-table (4.0.0)
|
||||
unicode-display_width (>= 1.1.1, < 4)
|
||||
thor (1.3.1)
|
||||
thor (1.4.0)
|
||||
thread-local (1.1.0)
|
||||
tilt (2.3.0)
|
||||
timecop (0.9.8)
|
||||
timeout (0.4.1)
|
||||
ttfunk (1.7.0)
|
||||
timecop (0.9.10)
|
||||
timeout (0.4.3)
|
||||
ttfunk (1.8.0)
|
||||
bigdecimal (~> 3.1)
|
||||
turbo-rails (2.0.5)
|
||||
actionpack (>= 6.0.0)
|
||||
activejob (>= 6.0.0)
|
||||
@@ -808,14 +854,17 @@ GEM
|
||||
turbo-rails (>= 1.3.0)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
undercover (0.6.3)
|
||||
undercover (0.7.4)
|
||||
base64
|
||||
bigdecimal
|
||||
imagen (>= 0.2.0)
|
||||
rainbow (>= 2.1, < 4.0)
|
||||
rugged (>= 0.27, < 1.8)
|
||||
rugged (>= 0.27, < 1.10)
|
||||
simplecov
|
||||
simplecov_json_formatter
|
||||
unicode-display_width (2.5.0)
|
||||
uniform_notifier (1.16.0)
|
||||
uri (0.13.0)
|
||||
uniform_notifier (1.17.0)
|
||||
uri (0.13.2)
|
||||
valid_email2 (5.2.3)
|
||||
activemodel (>= 3.2)
|
||||
mail (~> 2.5)
|
||||
@@ -855,7 +904,7 @@ GEM
|
||||
rack-proxy (>= 0.6.1)
|
||||
railties (>= 5.2)
|
||||
semantic_range (>= 2.3.0)
|
||||
webrick (1.8.1)
|
||||
webrick (1.8.2)
|
||||
websocket-driver (0.7.6)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.5)
|
||||
@@ -895,6 +944,7 @@ DEPENDENCIES
|
||||
cable_ready
|
||||
cancancan (~> 1.15.0)
|
||||
capybara
|
||||
capybara-shadowdom
|
||||
catalog!
|
||||
coffee-rails (~> 5.0.0)
|
||||
combine_pdf
|
||||
@@ -958,6 +1008,7 @@ DEPENDENCIES
|
||||
pg (~> 1.2.3)
|
||||
private_address_check
|
||||
pry (~> 0.13.0)
|
||||
puffing-billy
|
||||
puma
|
||||
query_count
|
||||
rack-mini-profiler (< 3.0.0)
|
||||
@@ -989,7 +1040,6 @@ DEPENDENCIES
|
||||
sidekiq
|
||||
sidekiq-scheduler
|
||||
simplecov
|
||||
simplecov-lcov
|
||||
spreadsheet_architect
|
||||
spring
|
||||
spring-commands-rspec
|
||||
|
||||
@@ -1,390 +0,0 @@
|
||||
angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout, $filter, $http, $window, $location, BulkProducts, DisplayProperties, DirtyProducts, VariantUnitManager, StatusMessage, producers, Taxons, Columns, tax_categories, RequestMonitor, SortOptions, ErrorsParser, ProductFiltersUrl) ->
|
||||
$scope.StatusMessage = StatusMessage
|
||||
|
||||
$scope.columns = Columns.columns
|
||||
|
||||
$scope.variant_unit_options = VariantUnitManager.variantUnitOptions()
|
||||
|
||||
$scope.RequestMonitor = RequestMonitor
|
||||
$scope.pagination = BulkProducts.pagination
|
||||
$scope.per_page_options = [
|
||||
{id: 15, name: t('js.admin.orders.index.per_page', results: 15)},
|
||||
{id: 50, name: t('js.admin.orders.index.per_page', results: 50)},
|
||||
{id: 100, name: t('js.admin.orders.index.per_page', results: 100)}
|
||||
]
|
||||
|
||||
$scope.q = {
|
||||
producerFilter: ""
|
||||
categoryFilter: ""
|
||||
importDateFilter: ""
|
||||
query: ""
|
||||
sorting: ""
|
||||
}
|
||||
|
||||
$scope.sorting = "name asc"
|
||||
$scope.producers = producers
|
||||
$scope.taxons = Taxons.all
|
||||
$scope.tax_categories = tax_categories
|
||||
$scope.page = 1
|
||||
$scope.per_page = 15
|
||||
$scope.products = BulkProducts.products
|
||||
$scope.DisplayProperties = DisplayProperties
|
||||
|
||||
$scope.sortOptions = SortOptions
|
||||
|
||||
$scope.initialise = ->
|
||||
$scope.q = ProductFiltersUrl.loadFromUrl($location.search())
|
||||
$scope.fetchProducts()
|
||||
|
||||
$scope.$watchCollection '[q.query, q.producerFilter, q.categoryFilter, q.importDateFilter, per_page]', ->
|
||||
$scope.page = 1 # Reset page when changing filters for new search
|
||||
|
||||
$scope.changePage = (newPage) ->
|
||||
$scope.page = newPage
|
||||
$scope.fetchProducts()
|
||||
|
||||
$scope.fetchProducts = ->
|
||||
removeClearedValues()
|
||||
params = {
|
||||
'q[name_cont]': $scope.q.query,
|
||||
'q[variants_supplier_id_eq]': $scope.q.producerFilter,
|
||||
'q[variants_primary_taxon_id_eq]': $scope.q.categoryFilter,
|
||||
'q[s]': $scope.sorting,
|
||||
import_date: $scope.q.importDateFilter,
|
||||
page: $scope.page,
|
||||
per_page: $scope.per_page
|
||||
}
|
||||
RequestMonitor.load(BulkProducts.fetch(params).$promise).then ->
|
||||
# update url with the filters used
|
||||
$location.search(ProductFiltersUrl.generate($scope.q))
|
||||
$scope.resetProducts()
|
||||
|
||||
removeClearedValues = ->
|
||||
delete $scope.q.producerFilter if $scope.q.producerFilter == "0"
|
||||
delete $scope.q.categoryFilter if $scope.q.categoryFilter == "0"
|
||||
delete $scope.q.importDateFilter if $scope.q.importDateFilter == "0"
|
||||
|
||||
$timeout ->
|
||||
if $scope.showLatestImport
|
||||
$scope.q.importDateFilter = $scope.importDates[1].id
|
||||
|
||||
$scope.resetProducts = ->
|
||||
DirtyProducts.clear()
|
||||
StatusMessage.clear()
|
||||
|
||||
$scope.updateOnHand = (product) ->
|
||||
on_demand_variants = []
|
||||
if product.variants
|
||||
on_demand_variants = (variant for id, variant of product.variants when variant.on_demand)
|
||||
|
||||
unless product.on_demand || on_demand_variants.length > 0
|
||||
product.on_hand = $scope.onHand(product)
|
||||
|
||||
|
||||
$scope.onHand = (product) ->
|
||||
onHand = 0
|
||||
if product.hasOwnProperty("variants") and product.variants instanceof Object
|
||||
for id, variant of product.variants
|
||||
onHand = onHand + parseInt(if variant.on_hand > 0 then variant.on_hand else 0)
|
||||
else
|
||||
onHand = "error"
|
||||
onHand
|
||||
|
||||
$scope.shiftTab = (tab) ->
|
||||
$scope.visibleTab.visible = false unless $scope.visibleTab == tab || $scope.visibleTab == undefined
|
||||
tab.visible = !tab.visible
|
||||
$scope.visibleTab = tab
|
||||
|
||||
$scope.resetSelectFilters = ->
|
||||
$scope.q.query = ""
|
||||
$scope.q.producerFilter = "0"
|
||||
$scope.q.categoryFilter = "0"
|
||||
$scope.q.importDateFilter = "0"
|
||||
$scope.fetchProducts()
|
||||
|
||||
$scope.$watch 'sortOptions', (sort) ->
|
||||
return unless sort && sort.predicate != ""
|
||||
|
||||
$scope.sorting = sort.getSortingExpr(defaultDirection: "asc")
|
||||
$scope.fetchProducts()
|
||||
, true
|
||||
|
||||
confirm_unsaved_changes = () ->
|
||||
(DirtyProducts.count() > 0 and confirm(t("unsaved_changes_confirmation"))) or (DirtyProducts.count() == 0)
|
||||
|
||||
editProductUrl = (product, variant) ->
|
||||
"/admin/products/" + product.id + ((if variant then "/variants/" + variant.id else "")) + "/edit"
|
||||
|
||||
$scope.editWarn = (product, variant) ->
|
||||
if confirm_unsaved_changes()
|
||||
$window.location.href = ProductFiltersUrl.buildUrl(editProductUrl(product, variant), $scope.q)
|
||||
|
||||
$scope.toggleShowAllVariants = ->
|
||||
showVariants = !DisplayProperties.showVariants 0
|
||||
$scope.products.forEach (product) ->
|
||||
DisplayProperties.setShowVariants product.id, showVariants
|
||||
DisplayProperties.setShowVariants 0, showVariants
|
||||
|
||||
$scope.addVariant = (product) ->
|
||||
# Set new variant category to same as last product variant category to keep compactibility with deleted variant callback to set new variant category
|
||||
newVariantId = $scope.nextVariantId();
|
||||
newVariantCategoryId = product.variants[product.variants.length - 1]?.category_id
|
||||
product.variants.push
|
||||
id: newVariantId
|
||||
unit_value: null
|
||||
unit_description: null
|
||||
on_demand: false
|
||||
display_as: null
|
||||
display_name: null
|
||||
on_hand: null
|
||||
price: null
|
||||
tax_category_id: null
|
||||
category_id: newVariantCategoryId
|
||||
DisplayProperties.setShowVariants product.id, true
|
||||
DirtyProducts.addVariantProperty(product.id, newVariantId, 'category_id', newVariantCategoryId)
|
||||
|
||||
|
||||
$scope.nextVariantId = ->
|
||||
$scope.variantIdCounter = 0 unless $scope.variantIdCounter?
|
||||
$scope.variantIdCounter -= 1
|
||||
$scope.variantIdCounter
|
||||
|
||||
$scope.deleteProduct = (product) ->
|
||||
if confirm(t('are_you_sure'))
|
||||
$http(
|
||||
method: "DELETE"
|
||||
url: "/api/v0/products/" + product.id
|
||||
).then (response) ->
|
||||
$scope.products.splice $scope.products.indexOf(product), 1
|
||||
DirtyProducts.deleteProduct product.id
|
||||
$scope.displayDirtyProducts()
|
||||
|
||||
|
||||
$scope.deleteVariant = (product, variant) ->
|
||||
if product.variants.length > 1
|
||||
if !$scope.variantSaved(variant)
|
||||
$scope.removeVariant(product, variant)
|
||||
else
|
||||
if confirm(t("are_you_sure"))
|
||||
$http(
|
||||
method: "DELETE"
|
||||
url: "/api/v0/products/" + product.id + "/variants/" + variant.id
|
||||
).then (response) ->
|
||||
$scope.removeVariant(product, variant)
|
||||
else
|
||||
alert(t("delete_product_variant"))
|
||||
|
||||
$scope.removeVariant = (product, variant) ->
|
||||
product.variants.splice product.variants.indexOf(variant), 1
|
||||
DirtyProducts.deleteVariant product.id, variant.id
|
||||
$scope.displayDirtyProducts()
|
||||
|
||||
|
||||
$scope.cloneProduct = (product) ->
|
||||
BulkProducts.cloneProduct product
|
||||
|
||||
$scope.hasVariants = (product) ->
|
||||
product.variants.length > 0
|
||||
|
||||
|
||||
$scope.hasUnit = (variant) ->
|
||||
variant.variant_unit_with_scale?
|
||||
|
||||
$scope.variantSaved = (variant) ->
|
||||
variant.hasOwnProperty('id') && variant.id > 0
|
||||
|
||||
|
||||
$scope.hasOnDemandVariants = (product) ->
|
||||
(variant for id, variant of product.variants when variant.on_demand).length > 0
|
||||
|
||||
|
||||
$scope.submitProducts = ->
|
||||
# Pack pack $scope.products, so they will match the list returned from the server,
|
||||
# then pack $scope.dirtyProducts, ensuring that the correct product info is sent to the server.
|
||||
$scope.packProduct product for id, product of $scope.products
|
||||
$scope.packProduct product for id, product of DirtyProducts.all()
|
||||
|
||||
productsToSubmit = filterSubmitProducts(DirtyProducts.all())
|
||||
if productsToSubmit.length > 0
|
||||
$scope.updateProducts productsToSubmit # Don't submit an empty list
|
||||
else
|
||||
StatusMessage.display 'alert', t("products_change")
|
||||
|
||||
|
||||
$scope.updateProducts = (productsToSubmit) ->
|
||||
$scope.displayUpdating()
|
||||
$http(
|
||||
method: "POST"
|
||||
url: "/admin/products/bulk_update"
|
||||
data:
|
||||
products: productsToSubmit
|
||||
filters:
|
||||
'q[name_cont]': $scope.q.query
|
||||
'q[variants_supplier_id_eq]': $scope.q.producerFilter
|
||||
'q[variants_primary_taxon_id_eq]': $scope.q.categoryFilter
|
||||
'q[s]': $scope.sorting
|
||||
import_date: $scope.q.importDateFilter
|
||||
page: $scope.page
|
||||
per_page: $scope.per_page
|
||||
).then((response) ->
|
||||
DirtyProducts.clear()
|
||||
BulkProducts.updateVariantLists(response.data.products || [])
|
||||
$timeout -> $scope.displaySuccess()
|
||||
).catch (response) ->
|
||||
if response.status == 400 && response.data.errors?
|
||||
errorsString = ErrorsParser.toString(response.data.errors, response.status)
|
||||
$scope.displayFailure t("products_update_error") + "\n" + errorsString
|
||||
else
|
||||
$scope.displayFailure t("products_update_error_data") + response.status
|
||||
|
||||
$scope.cancel = (destination) ->
|
||||
$window.location = destination
|
||||
|
||||
$scope.packProduct = (product) ->
|
||||
if product.variants
|
||||
for id, variant of product.variants
|
||||
$scope.packVariant variant
|
||||
|
||||
|
||||
$scope.packVariant = (variant) ->
|
||||
if variant.variant_unit_with_scale
|
||||
match = variant.variant_unit_with_scale.match(/^([^_]+)_([\d\.]+)$/)
|
||||
if match
|
||||
variant.variant_unit = match[1]
|
||||
variant.variant_unit_scale = parseFloat(match[2])
|
||||
else
|
||||
variant.variant_unit = variant.variant_unit_with_scale
|
||||
variant.variant_unit_scale = null
|
||||
|
||||
if variant.hasOwnProperty("unit_value_with_description")
|
||||
match = variant.unit_value_with_description.match(/^([\d\.\,]+(?= |$)|)( |)(.*)$/)
|
||||
if match
|
||||
variant.unit_value = parseFloat(match[1].replace(",", "."))
|
||||
variant.unit_value = null if isNaN(variant.unit_value)
|
||||
if variant.unit_value && variant.variant_unit_scale
|
||||
variant.unit_value = parseFloat(window.bigDecimal.multiply(variant.unit_value, variant.variant_unit_scale, 2))
|
||||
variant.unit_description = match[3]
|
||||
|
||||
$scope.incrementLimit = ->
|
||||
if $scope.limit < $scope.products.length
|
||||
$scope.limit = $scope.limit + 5
|
||||
|
||||
|
||||
$scope.displayUpdating = ->
|
||||
StatusMessage.display 'progress', t("saving")
|
||||
|
||||
|
||||
$scope.displaySuccess = ->
|
||||
StatusMessage.display 'success',t("products_changes_saved")
|
||||
$scope.bulk_product_form.$setPristine()
|
||||
|
||||
|
||||
$scope.displayFailure = (failMessage) ->
|
||||
StatusMessage.display 'failure', t("products_update_error_msg") + " #{failMessage}"
|
||||
|
||||
|
||||
$scope.displayDirtyProducts = ->
|
||||
count = DirtyProducts.count()
|
||||
switch count
|
||||
when 0 then StatusMessage.clear()
|
||||
when 1 then StatusMessage.display 'notice', t("one_product_unsaved")
|
||||
else StatusMessage.display 'notice', t("products_unsaved", n: count)
|
||||
|
||||
|
||||
filterSubmitProducts = (productsToFilter) ->
|
||||
filteredProducts = []
|
||||
if productsToFilter instanceof Object
|
||||
angular.forEach productsToFilter, (product) ->
|
||||
if product.hasOwnProperty("id")
|
||||
filteredProduct = {id: product.id}
|
||||
filteredVariants = []
|
||||
hasUpdatableProperty = false
|
||||
|
||||
if product.hasOwnProperty("variants")
|
||||
angular.forEach product.variants, (variant) ->
|
||||
result = filterSubmitVariant variant
|
||||
filteredVariant = result.filteredVariant
|
||||
variantHasUpdatableProperty = result.hasUpdatableProperty
|
||||
filteredVariants.push filteredVariant if variantHasUpdatableProperty
|
||||
|
||||
if product.hasOwnProperty("name")
|
||||
filteredProduct.name = product.name
|
||||
hasUpdatableProperty = true
|
||||
if product.hasOwnProperty("price")
|
||||
filteredProduct.price = product.price
|
||||
hasUpdatableProperty = true
|
||||
if product.hasOwnProperty("on_hand") and filteredVariants.length == 0 #only update if no variants present
|
||||
filteredProduct.on_hand = product.on_hand
|
||||
hasUpdatableProperty = true
|
||||
if product.hasOwnProperty("on_demand") and filteredVariants.length == 0 #only update if no variants present
|
||||
filteredProduct.on_demand = product.on_demand
|
||||
hasUpdatableProperty = true
|
||||
if product.hasOwnProperty("inherits_properties")
|
||||
filteredProduct.inherits_properties = product.inherits_properties
|
||||
hasUpdatableProperty = true
|
||||
if filteredVariants.length > 0 # Note that the name of the property changes to enable mass assignment of variants attributes with rails
|
||||
filteredProduct.variants_attributes = filteredVariants
|
||||
hasUpdatableProperty = true
|
||||
filteredProducts.push filteredProduct if hasUpdatableProperty
|
||||
|
||||
filteredProducts
|
||||
|
||||
|
||||
filterSubmitVariant = (variant) ->
|
||||
hasUpdatableProperty = false
|
||||
filteredVariant = {}
|
||||
if not variant.deleted_at? and variant.hasOwnProperty("id")
|
||||
filteredVariant.id = variant.id unless variant.id <= 0
|
||||
if variant.hasOwnProperty("sku")
|
||||
filteredVariant.sku = variant.sku
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("on_hand")
|
||||
filteredVariant.on_hand = variant.on_hand
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("on_demand")
|
||||
filteredVariant.on_demand = variant.on_demand
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("price")
|
||||
filteredVariant.price = variant.price
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("unit_value")
|
||||
filteredVariant.unit_value = variant.unit_value
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("unit_description")
|
||||
filteredVariant.unit_description = variant.unit_description
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("display_name")
|
||||
filteredVariant.display_name = variant.display_name
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("tax_category_id")
|
||||
filteredVariant.tax_category_id = variant.tax_category_id
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("category_id")
|
||||
filteredVariant.primary_taxon_id = variant.category_id
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("display_as")
|
||||
filteredVariant.display_as = variant.display_as
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("producer_id")
|
||||
filteredVariant.supplier_id = variant.producer_id
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("variant_unit_with_scale")
|
||||
filteredVariant.variant_unit = variant.variant_unit
|
||||
filteredVariant.variant_unit_scale = variant.variant_unit_scale
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("variant_unit_name")
|
||||
filteredVariant.variant_unit_name = variant.variant_unit_name
|
||||
hasUpdatableProperty = true
|
||||
|
||||
{filteredVariant: filteredVariant, hasUpdatableProperty: hasUpdatableProperty}
|
||||
|
||||
|
||||
toObjectWithIDKeys = (array) ->
|
||||
object = {}
|
||||
|
||||
for i of array
|
||||
if array[i] instanceof Object and array[i].hasOwnProperty("id")
|
||||
object[array[i].id] = angular.copy(array[i])
|
||||
object[array[i].id].variants = toObjectWithIDKeys(array[i].variants) if array[i].hasOwnProperty("variants") and array[i].variants instanceof Array
|
||||
|
||||
object
|
||||
@@ -19,18 +19,6 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
$scope.page = 1
|
||||
$scope.per_page = $scope.per_page_options[0].id
|
||||
$scope.filterByVariantId = null
|
||||
searchThrough = ["order_distributor_name",
|
||||
"order_bill_address_phone",
|
||||
"order_bill_address_firstname",
|
||||
"order_bill_address_lastname",
|
||||
"order_bill_address_full_name",
|
||||
"order_bill_address_full_name_reversed",
|
||||
"order_bill_address_full_name_with_comma",
|
||||
"order_bill_address_full_name_with_comma_reversed",
|
||||
"variant_supplier_name",
|
||||
"order_email",
|
||||
"order_number",
|
||||
"product_name"].join("_or_") + "_cont"
|
||||
|
||||
$scope.confirmRefresh = ->
|
||||
LineItems.allSaved() || confirm(t("unsaved_changes_warning"))
|
||||
@@ -75,11 +63,10 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
[formattedStartDate, formattedEndDate] = $scope.formatDates($scope.startDate, $scope.endDate)
|
||||
|
||||
RequestMonitor.load LineItems.index(
|
||||
"q[#{searchThrough}]": $scope.query,
|
||||
"q[variant_id_eq]": $scope.filterByVariantId if $scope.filterByVariantId,
|
||||
"q[order_state_not_eq]": "canceled",
|
||||
"q[order_shipment_state_not_eq]": "shipped",
|
||||
"q[order_completed_at_not_null]": "true",
|
||||
"q[variant_id_eq]": $scope.filterByVariantId if $scope.filterByVariantId,
|
||||
"q[order_distributor_id_eq]": $scope.distributorFilter,
|
||||
"q[variant_supplier_id_eq]": $scope.supplierFilter,
|
||||
"q[order_order_cycle_id_eq]": $scope.orderCycleFilter,
|
||||
@@ -87,7 +74,8 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
"q[order_completed_at_lt]": if formattedEndDate then formattedEndDate else undefined,
|
||||
"q[s]": "order_completed_at desc",
|
||||
"page": $scope.page,
|
||||
"per_page": $scope.per_page
|
||||
"per_page": $scope.per_page,
|
||||
"search_query": $scope.query
|
||||
)
|
||||
|
||||
$scope.formatDates = (startDate, endDate) ->
|
||||
|
||||
@@ -5,6 +5,8 @@ angular.module("admin.orders").controller "orderCtrl", ($scope, shops, orderCycl
|
||||
|
||||
$scope.distributor_id = parseInt($attrs.ofnDistributorId)
|
||||
$scope.order_cycle_id = parseInt($attrs.ofnOrderCycleId)
|
||||
$scope.search_variants_as = $attrs.ofnSearchVariantsAs
|
||||
$scope.order_id = $attrs.ofnOrderId
|
||||
|
||||
$scope.validOrderCycle = (oc) ->
|
||||
$scope.orderCycleHasDistributor oc, parseInt($scope.distributor_id)
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
angular.module("ofn.admin").controller "ProductImageCtrl", ($scope, ProductImageService) ->
|
||||
$scope.imageUploader = ProductImageService.imageUploader
|
||||
$scope.imagePreview = ProductImageService.imagePreview
|
||||
|
||||
$scope.$watch 'product.image_url', (newValue, oldValue) ->
|
||||
if newValue != oldValue
|
||||
$scope.imagePreview = newValue
|
||||
$scope.uploadModal.close()
|
||||
@@ -1,6 +0,0 @@
|
||||
angular.module("ofn.admin").directive "imageModal", ($modal, ProductImageService) ->
|
||||
restrict: 'C'
|
||||
link: (scope, elem, attrs, ctrl) ->
|
||||
elem.on "click", (ev) =>
|
||||
scope.uploadModal = $modal.open(templateUrl: 'admin/modals/image_upload.html', controller: ctrl, scope: scope, windowClass: 'simple-modal')
|
||||
ProductImageService.configure(scope.product)
|
||||
@@ -1,6 +0,0 @@
|
||||
angular.module("admin.resources").factory 'ProductResource', ($resource) ->
|
||||
$resource('/admin/product/:id/:action.json', {}, {
|
||||
'index':
|
||||
url: '/api/v0/products/bulk_products.json'
|
||||
method: 'GET'
|
||||
})
|
||||
@@ -1,76 +0,0 @@
|
||||
angular.module("ofn.admin").factory "BulkProducts", (ProductResource, dataFetcher, $http) ->
|
||||
new class BulkProducts
|
||||
products: []
|
||||
pagination: {}
|
||||
|
||||
fetch: (params) ->
|
||||
ProductResource.index params, (data) =>
|
||||
@products.length = 0
|
||||
@addProducts data.products
|
||||
angular.extend(@pagination, data.pagination)
|
||||
|
||||
cloneProduct: (product) ->
|
||||
$http.post("/api/v0/products/" + product.id + "/clone").then (response) =>
|
||||
dataFetcher("/api/v0/products/" + response.data.id + "?template=bulk_show").then (newProduct) =>
|
||||
@unpackProduct newProduct
|
||||
@insertProductAfter(product, newProduct)
|
||||
|
||||
updateVariantLists: (serverProducts) ->
|
||||
for server_product in serverProducts
|
||||
product = @findProductInList(server_product.id, @products)
|
||||
product.variants = server_product.variants
|
||||
@loadVariantUnitValues product.variants
|
||||
|
||||
find: (id) ->
|
||||
@findProductInList id, @products
|
||||
|
||||
findProductInList: (id, product_list) ->
|
||||
products = (product for product in product_list when product.id == id)
|
||||
if products.length == 0 then null else products[0]
|
||||
|
||||
addProducts: (products) ->
|
||||
for product in products
|
||||
@unpackProduct product
|
||||
@products.push product
|
||||
|
||||
insertProductAfter: (product, newProduct) ->
|
||||
index = @products.indexOf(product)
|
||||
@products.splice(index + 1, 0, newProduct)
|
||||
|
||||
unpackProduct: (product) ->
|
||||
@loadVariantUnit product
|
||||
|
||||
loadVariantUnit: (product) ->
|
||||
@loadVariantUnitValues product.variants if product.variants
|
||||
|
||||
loadVariantUnitValues: (variants) ->
|
||||
for variant in variants
|
||||
@loadVariantUnitValue variant
|
||||
|
||||
loadVariantUnitValue: (variant) ->
|
||||
variant.variant_unit_with_scale =
|
||||
if variant.variant_unit && variant.variant_unit_scale && variant.variant_unit != 'items'
|
||||
"#{variant.variant_unit}_#{variant.variant_unit_scale}"
|
||||
else if variant.variant_unit
|
||||
variant.variant_unit
|
||||
else
|
||||
null
|
||||
|
||||
unit_value = @variantUnitValue variant
|
||||
unit_value = if unit_value? then unit_value else ''
|
||||
variant.unit_value_with_description = "#{unit_value} #{variant.unit_description || ''}".trim()
|
||||
|
||||
variantUnitValue: (variant) ->
|
||||
if variant.unit_value?
|
||||
if variant.variant_unit_scale
|
||||
variant_unit_value = @divideAsInteger variant.unit_value, variant.variant_unit_scale
|
||||
parseFloat(window.bigDecimal.round(variant_unit_value, 2))
|
||||
else
|
||||
variant.unit_value
|
||||
else
|
||||
null
|
||||
|
||||
# forces integer division to avoid javascript floating point imprecision
|
||||
# using one billion as the multiplier so that it works for numbers with up to 9 decimal places
|
||||
divideAsInteger: (a, b) ->
|
||||
(a * 1000000000) / (b * 1000000000)
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("admin.tagRules").directive 'newTagRuleDialog', ($rootScope, $compile, $templateCache, DialogDefaults) ->
|
||||
angular.module("admin.tagRules").directive 'newTagRuleDialog', ($rootScope, $compile, $templateCache, DialogDefaults, ruleTypes) ->
|
||||
restrict: 'A'
|
||||
scope:
|
||||
tagGroup: '='
|
||||
@@ -7,12 +7,7 @@ angular.module("admin.tagRules").directive 'newTagRuleDialog', ($rootScope, $com
|
||||
# Compile modal template
|
||||
template = $compile($templateCache.get('admin/new_tag_rule_dialog.html'))(scope)
|
||||
|
||||
scope.ruleTypes = [
|
||||
{ id: "FilterProducts", name: t('js.tag_rules.show_hide_variants') }
|
||||
{ id: "FilterShippingMethods", name: t('js.tag_rules.show_hide_shipping') }
|
||||
{ id: "FilterPaymentMethods", name: t('js.tag_rules.show_hide_payment') }
|
||||
{ id: "FilterOrderCycles", name: t('js.tag_rules.show_hide_order_cycles') }
|
||||
]
|
||||
scope.ruleTypes = ruleTypes
|
||||
|
||||
scope.ruleType = scope.ruleTypes[0].id
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ angular.module("admin.utils").directive "variantAutocomplete", ($timeout) ->
|
||||
order_cycle_id: scope.order_cycle_id
|
||||
eligible_for_subscriptions: scope.eligible_for_subscriptions
|
||||
include_out_of_stock: scope.include_out_of_stock
|
||||
search_variants_as: scope.search_variants_as
|
||||
order_id: scope.order_id
|
||||
results: (data, page) ->
|
||||
window.variants = data # this is how spree auto complete JS code picks up variants
|
||||
results: data
|
||||
|
||||
@@ -12,7 +12,7 @@ module Admin
|
||||
@line_items = order_permissions.
|
||||
editable_line_items.where(order_id: orders).
|
||||
includes(:variant).
|
||||
ransack(params[:q]).result.order(:id)
|
||||
ransack(line_items_search_query).result.order(:id)
|
||||
|
||||
@pagy, @line_items = pagy(@line_items) if pagination_required?
|
||||
|
||||
@@ -88,5 +88,27 @@ module Admin
|
||||
def page
|
||||
params[:page] || 1
|
||||
end
|
||||
|
||||
def line_items_search_query
|
||||
query = params.permit(q: {}).to_h[:q] || {}
|
||||
|
||||
search_fields_string = [
|
||||
spree_current_user.admin? ? "order_distributor_name" : "order_distributor_name_alias",
|
||||
"order_bill_address_phone",
|
||||
"order_bill_address_firstname",
|
||||
"order_bill_address_lastname",
|
||||
"order_bill_address_full_name",
|
||||
"order_bill_address_full_name_reversed",
|
||||
"order_bill_address_full_name_with_comma",
|
||||
"order_bill_address_full_name_with_comma_reversed",
|
||||
"variant_supplier_name",
|
||||
"order_email",
|
||||
"order_number",
|
||||
"product_name"
|
||||
].join("_or_")
|
||||
search_query = "#{search_fields_string}_cont"
|
||||
|
||||
query.merge({ search_query => params[:search_query] })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -48,6 +48,9 @@ module Admin
|
||||
@object = Enterprise.where(permalink: params[:id]).
|
||||
includes(users: [:ship_address, :bill_address]).first
|
||||
@object.build_custom_tab if @object.custom_tab.nil?
|
||||
|
||||
load_tag_rule_types
|
||||
|
||||
return unless params[:stimulus]
|
||||
|
||||
@enterprise.is_primary_producer = params[:is_primary_producer]
|
||||
@@ -375,6 +378,19 @@ module Admin
|
||||
@properties = Spree::Property.pluck(:name)
|
||||
end
|
||||
|
||||
def load_tag_rule_types
|
||||
# Load rule types
|
||||
@tag_rule_types = [
|
||||
{ id: "FilterShippingMethods", name: t('js.tag_rules.show_hide_shipping') },
|
||||
{ id: "FilterPaymentMethods", name: t('js.tag_rules.show_hide_payment') },
|
||||
{ id: "FilterOrderCycles", name: t('js.tag_rules.show_hide_order_cycles') }
|
||||
]
|
||||
|
||||
return unless helpers.feature?(:inventory, @object)
|
||||
|
||||
@tag_rule_types.prepend({ id: "FilterProducts", name: t('js.tag_rules.show_hide_variants') })
|
||||
end
|
||||
|
||||
def setup_property
|
||||
@enterprise.producer_properties.build
|
||||
end
|
||||
|
||||
@@ -17,7 +17,10 @@ module Admin
|
||||
end
|
||||
|
||||
def import
|
||||
return unless can_import_into_inventories?
|
||||
|
||||
@filepath = save_uploaded_file(params[:file])
|
||||
|
||||
@importer = ProductImport::ProductImporter.new(File.new(@filepath), spree_current_user,
|
||||
params[:settings])
|
||||
@original_filename = params[:file].try(:original_filename)
|
||||
@@ -36,7 +39,22 @@ module Admin
|
||||
def save_data
|
||||
return unless process_data('save')
|
||||
|
||||
render json: @importer.save_results
|
||||
json = {
|
||||
results: {
|
||||
products_created: @importer.products_created_count,
|
||||
products_updated: @importer.products_updated_count,
|
||||
products_reset: @importer.products_reset_count,
|
||||
},
|
||||
updated_ids: @importer.updated_ids,
|
||||
errors: @importer.errors.full_messages
|
||||
}
|
||||
|
||||
if helpers.feature?(:inventory, spree_current_user.enterprises)
|
||||
json[:results][:inventory_created] = @importer.inventory_created_count
|
||||
json[:results][:inventory_updated] = @importer.inventory_updated_count
|
||||
end
|
||||
|
||||
render json:
|
||||
end
|
||||
|
||||
def reset_absent_products
|
||||
@@ -154,5 +172,15 @@ module Admin
|
||||
notice: I18n.t(:product_import_no_data_in_spreadsheet_notice)
|
||||
raise 'Invalid File Path'
|
||||
end
|
||||
|
||||
# Return an error if trying to import into inventories when inventory is disable
|
||||
def can_import_into_inventories?
|
||||
return true if helpers.feature?(:inventory, spree_current_user.enterprises) ||
|
||||
params.dig(:settings, "import_into") != 'inventories'
|
||||
|
||||
redirect_to admin_product_import_url, notice: I18n.t(:product_import_inventory_disable)
|
||||
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -53,7 +53,9 @@ module Admin
|
||||
return unless @order_cycle
|
||||
|
||||
fee_calculator = OpenFoodNetwork::EnterpriseFeeCalculator.new(@shop, @order_cycle)
|
||||
|
||||
OpenFoodNetwork::ScopeVariantToHub.new(@shop).scope(@variant)
|
||||
|
||||
@variant.price + fee_calculator.indexed_fees_for(@variant)
|
||||
end
|
||||
|
||||
|
||||
@@ -22,7 +22,8 @@ module Api
|
||||
distributor,
|
||||
order_cycle,
|
||||
customer,
|
||||
search_params
|
||||
search_params,
|
||||
inventory_enabled:
|
||||
).products_json
|
||||
|
||||
render plain: products
|
||||
@@ -95,9 +96,13 @@ module Api
|
||||
|
||||
def distributed_products
|
||||
OrderCycles::DistributedProductsService.new(
|
||||
distributor, order_cycle, customer
|
||||
distributor, order_cycle, customer, inventory_enabled:
|
||||
).products_relation.pluck(:id)
|
||||
end
|
||||
|
||||
def inventory_enabled
|
||||
OpenFoodNetwork::FeatureToggle.enabled?(:inventory, distributor)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -112,7 +112,9 @@ module Api
|
||||
|
||||
def scoped_variant(variant_id)
|
||||
variant = Spree::Variant.find(variant_id)
|
||||
|
||||
OpenFoodNetwork::ScopeVariantToHub.new(@order.distributor).scope(variant)
|
||||
|
||||
variant
|
||||
end
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ module Api
|
||||
def error_during_processing(exception)
|
||||
Alert.raise(exception)
|
||||
|
||||
if Rails.env.development? || Rails.env.test?
|
||||
if Rails.env.local?
|
||||
render status: :unprocessable_entity,
|
||||
json: json_api_error(exception.message, meta: exception.backtrace)
|
||||
else
|
||||
|
||||
@@ -80,8 +80,6 @@ class CheckoutController < BaseController
|
||||
|
||||
@order.customer.touch :terms_and_conditions_accepted_at
|
||||
|
||||
return true if redirect_to_payment_gateway
|
||||
|
||||
# Redeem VINE voucher
|
||||
vine_voucher_redeemer = Vine::VoucherRedeemerService.new(order: @order)
|
||||
unless vine_voucher_redeemer.redeem
|
||||
@@ -94,6 +92,9 @@ class CheckoutController < BaseController
|
||||
return false
|
||||
# rubocop:enable Rails/DeprecatedActiveModelErrorsMethods
|
||||
end
|
||||
|
||||
return true if redirect_to_payment_gateway
|
||||
|
||||
@order.process_payments!
|
||||
@order.confirm!
|
||||
BackorderJob.check_stock(@order)
|
||||
|
||||
@@ -19,11 +19,6 @@ module Spree
|
||||
before_action :load_spree_api_key, only: [:index, :variant_overrides]
|
||||
before_action :strip_new_properties, only: [:create, :update]
|
||||
|
||||
def index
|
||||
@current_user = spree_current_user
|
||||
@show_latest_import = params[:latest_import] || false
|
||||
end
|
||||
|
||||
def show
|
||||
session[:return_to] ||= request.referer
|
||||
redirect_to( action: :edit )
|
||||
@@ -65,28 +60,6 @@ module Spree
|
||||
end
|
||||
end
|
||||
|
||||
def bulk_update
|
||||
product_set = product_set_from_params
|
||||
|
||||
product_set.collection.each { |p| authorize! :update, p }
|
||||
|
||||
if product_set.save
|
||||
redirect_to main_app.bulk_products_api_v0_products_path(bulk_index_query)
|
||||
elsif product_set.errors.present?
|
||||
render json: { errors: product_set.errors }, status: :bad_request
|
||||
else
|
||||
render body: nil, status: :internal_server_error
|
||||
end
|
||||
end
|
||||
|
||||
def clone
|
||||
@new = @product.duplicate
|
||||
raise "Clone failed" unless @new.save
|
||||
|
||||
flash[:success] = t('.success')
|
||||
redirect_to spree.admin_products_url
|
||||
end
|
||||
|
||||
def group_buy_options
|
||||
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
|
||||
end
|
||||
|
||||
@@ -117,7 +117,7 @@ module Spree
|
||||
def variant_search_params
|
||||
params.permit(
|
||||
:q, :distributor_id, :order_cycle_id, :schedule_id, :eligible_for_subscriptions,
|
||||
:include_out_of_stock
|
||||
:include_out_of_stock, :search_variants_as, :order_id
|
||||
).to_h.with_indifferent_access
|
||||
end
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ module Admin
|
||||
enterprise.in?(spree_current_user.enterprises)
|
||||
end
|
||||
|
||||
def enterprise_side_menu_items(enterprise)
|
||||
def enterprise_side_menu_items(enterprise) # rubocop:disable Metrics/CyclomaticComplexity
|
||||
is_shop = enterprise.sells != "none"
|
||||
show_properties = !!enterprise.is_primary_producer
|
||||
show_shipping_methods = can?(:manage_shipping_methods, enterprise) && is_shop
|
||||
@@ -26,24 +26,35 @@ module Admin
|
||||
show_enterprise_fees = can?(:manage_enterprise_fees,
|
||||
enterprise) && (is_shop || enterprise.is_primary_producer)
|
||||
show_connected_apps = can?(:manage_connected_apps, enterprise) &&
|
||||
feature?(:connected_apps, spree_current_user, enterprise) &&
|
||||
Spree::Config.connected_apps_enabled.present?
|
||||
(connected_apps_enabled(enterprise).present? ||
|
||||
dfc_platforms_available?)
|
||||
show_inventory_settings = feature?(:inventory, spree_current_user.enterprises) && is_shop
|
||||
|
||||
build_enterprise_side_menu_items(
|
||||
is_shop:,
|
||||
show_options = {
|
||||
show_properties:,
|
||||
show_shipping_methods:,
|
||||
show_payment_methods:,
|
||||
show_enterprise_fees:,
|
||||
show_connected_apps:,
|
||||
)
|
||||
show_inventory_settings:,
|
||||
}
|
||||
|
||||
build_enterprise_side_menu_items(is_shop:, show_options:)
|
||||
end
|
||||
|
||||
def connected_apps_enabled
|
||||
def connected_apps_enabled(enterprise)
|
||||
return [] unless feature?(:connected_apps, spree_current_user, enterprise)
|
||||
|
||||
connected_apps_enabled = Spree::Config.connected_apps_enabled&.split(',') || []
|
||||
ConnectedApp::TYPES & connected_apps_enabled
|
||||
end
|
||||
|
||||
def dfc_platforms_available?
|
||||
DfcProvider::PlatformsController::PLATFORM_IDS.keys.any? do |id|
|
||||
feature?(id, spree_current_user)
|
||||
end
|
||||
end
|
||||
|
||||
def enterprise_attachment_removal_modal_id
|
||||
attachment_removal_parameter # remove_logo|remove_promo_image|remove_white_label_logo
|
||||
end
|
||||
@@ -62,14 +73,7 @@ module Admin
|
||||
|
||||
private
|
||||
|
||||
def build_enterprise_side_menu_items(
|
||||
is_shop:,
|
||||
show_properties:,
|
||||
show_shipping_methods:,
|
||||
show_payment_methods:,
|
||||
show_enterprise_fees:,
|
||||
show_connected_apps:
|
||||
)
|
||||
def build_enterprise_side_menu_items(is_shop:, show_options: ) # rubocop:disable Metrics/MethodLength
|
||||
[
|
||||
{ name: 'primary_details', icon_class: "icon-home", show: true, selected: 'selected' },
|
||||
{ name: 'address', icon_class: "icon-map-marker", show: true },
|
||||
@@ -78,19 +82,24 @@ module Admin
|
||||
{ name: 'about', icon_class: "icon-pencil", show: true, form_name: "about_us" },
|
||||
{ name: 'business_details', icon_class: "icon-briefcase", show: true },
|
||||
{ name: 'images', icon_class: "icon-picture", show: true },
|
||||
{ name: 'properties', icon_class: "icon-tags", show: show_properties },
|
||||
{ name: 'shipping_methods', icon_class: "icon-truck", show: show_shipping_methods },
|
||||
{ name: 'payment_methods', icon_class: "icon-money", show: show_payment_methods },
|
||||
{ name: 'enterprise_fees', icon_class: "icon-tasks", show: show_enterprise_fees },
|
||||
{ name: 'properties', icon_class: "icon-tags", show: show_options[:show_properties] },
|
||||
{ name: 'shipping_methods', icon_class: "icon-truck",
|
||||
show: show_options[:show_shipping_methods] },
|
||||
{ name: 'payment_methods', icon_class: "icon-money",
|
||||
show: show_options[:show_payment_methods] },
|
||||
{ name: 'enterprise_fees', icon_class: "icon-tasks",
|
||||
show: show_options[:show_enterprise_fees] },
|
||||
{ name: 'vouchers', icon_class: "icon-ticket", show: is_shop },
|
||||
{ name: 'enterprise_permissions', icon_class: "icon-plug", show: true,
|
||||
href: admin_enterprise_relationships_path },
|
||||
{ name: 'inventory_settings', icon_class: "icon-list-ol", show: is_shop },
|
||||
{ name: 'inventory_settings', icon_class: "icon-list-ol",
|
||||
show: show_options[:show_inventory_settings] },
|
||||
{ name: 'tag_rules', icon_class: "icon-random", show: is_shop },
|
||||
{ name: 'shop_preferences', icon_class: "icon-shopping-cart", show: is_shop },
|
||||
{ name: 'white_label', icon_class: "icon-leaf", show: true },
|
||||
{ name: 'users', icon_class: "icon-user", show: true },
|
||||
{ name: 'connected_apps', icon_class: "icon-puzzle-piece", show: show_connected_apps },
|
||||
{ name: 'connected_apps', icon_class: "icon-puzzle-piece",
|
||||
show: show_options[:show_connected_apps] },
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -32,12 +32,8 @@ module Admin
|
||||
[precised_unit_value, variant.unit_description].compact_blank.join(" ")
|
||||
end
|
||||
|
||||
def products_return_to_url(url_filters)
|
||||
if feature?(:admin_style_v3, spree_current_user)
|
||||
return session[:products_return_to_url] || admin_products_url
|
||||
end
|
||||
|
||||
"#{admin_products_path}#{url_filters.empty? ? '' : "#?#{url_filters.to_query}"}"
|
||||
def products_return_to_url
|
||||
session[:products_return_to_url] || admin_products_url
|
||||
end
|
||||
|
||||
# if user hasn't saved any preferences on products page and there's only one producer;
|
||||
|
||||
@@ -5,10 +5,6 @@ module CheckoutHelper
|
||||
order.ship_address == order.bill_address
|
||||
end
|
||||
|
||||
def guest_checkout_allowed?
|
||||
current_order.distributor.allow_guest_orders?
|
||||
end
|
||||
|
||||
def checkout_adjustments_for(order, opts = {})
|
||||
exclude = opts[:exclude] || {}
|
||||
reject_zero_amount = opts.fetch(:reject_zero_amount, true)
|
||||
|
||||
@@ -29,13 +29,7 @@ module Spree
|
||||
scope: [:admin, :tab]).capitalize
|
||||
|
||||
css_classes = []
|
||||
|
||||
if options[:icon] && !feature?(:admin_style_v3, spree_current_user)
|
||||
link = link_to_with_icon(options[:icon], titleized_label, destination_url)
|
||||
css_classes << 'tab-with-icon'
|
||||
else
|
||||
link = link_to(titleized_label, destination_url)
|
||||
end
|
||||
link = link_to(titleized_label, destination_url)
|
||||
|
||||
selected = if options[:match_path]
|
||||
PathChecker
|
||||
|
||||
@@ -155,8 +155,7 @@ module Spree
|
||||
end
|
||||
|
||||
def filter_by_supplier?(order)
|
||||
order.distributor&.enable_producers_to_edit_orders &&
|
||||
spree_current_user.can_manage_line_items_in_orders_only?
|
||||
can? :edit_as_producer_only, order
|
||||
end
|
||||
|
||||
def display_value_for_producer(order, value)
|
||||
|
||||
@@ -20,6 +20,10 @@ class ApplicationRecord < ActiveRecord::Base
|
||||
if ENV["S3_BUCKET"].present? && variant.service.public?
|
||||
variant.processed.url
|
||||
else
|
||||
unless variant.blob.persisted?
|
||||
raise "ActiveStorage blob for variant is not persisted. Cannot generate URL."
|
||||
end
|
||||
|
||||
url_for(variant)
|
||||
end
|
||||
end
|
||||
|
||||
15
app/models/dfc_permission.rb
Normal file
15
app/models/dfc_permission.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Authorisations of a user allowing a platform to access to data.
|
||||
class DfcPermission < ApplicationRecord
|
||||
SCOPES = %w[
|
||||
ReadEnterprise ReadProducts ReadOrders
|
||||
WriteEnterprise WriteProducts WriteOrders
|
||||
].freeze
|
||||
|
||||
belongs_to :user, class_name: "Spree::User"
|
||||
belongs_to :enterprise
|
||||
|
||||
validates :grantee, presence: true
|
||||
validates :scope, presence: true, inclusion: { in: SCOPES }
|
||||
end
|
||||
@@ -286,9 +286,13 @@ class OrderCycle < ApplicationRecord
|
||||
user_id: user,
|
||||
distributor_id: distributor,
|
||||
order_cycle_id: self)
|
||||
|
||||
items = Spree::LineItem.includes(:variant).joins(:order).merge(orders)
|
||||
|
||||
scoper = OpenFoodNetwork::ScopeVariantToHub.new(distributor)
|
||||
items = Spree::LineItem.includes(:variant).joins(:order).merge(orders).to_a
|
||||
items.each { |li| scoper.scope(li.variant) }
|
||||
|
||||
items
|
||||
end
|
||||
|
||||
def distributor_payment_methods
|
||||
|
||||
@@ -142,20 +142,6 @@ module ProductImport
|
||||
{ entries: entries_json, reset_counts: }
|
||||
end
|
||||
|
||||
def save_results
|
||||
{
|
||||
results: {
|
||||
products_created: products_created_count,
|
||||
products_updated: products_updated_count,
|
||||
inventory_created: inventory_created_count,
|
||||
inventory_updated: inventory_updated_count,
|
||||
products_reset: products_reset_count,
|
||||
},
|
||||
updated_ids:,
|
||||
errors: errors.full_messages
|
||||
}
|
||||
end
|
||||
|
||||
def validate_entries
|
||||
@validator.validate_all(@entries)
|
||||
end
|
||||
@@ -207,6 +193,8 @@ module ProductImport
|
||||
order('is_primary_producer ASC, name').
|
||||
map { |e| @editable_enterprises[e.name] = e.id }
|
||||
|
||||
return unless OpenFoodNetwork::FeatureToggle.enabled?(:inventory, @current_user.enterprises)
|
||||
|
||||
@inventory_permissions = permissions.variant_override_enterprises_per_hub
|
||||
end
|
||||
|
||||
|
||||
@@ -20,6 +20,10 @@ module Spree
|
||||
|
||||
if user.try(:admin?)
|
||||
can :manage, :all
|
||||
|
||||
# this action was needed for restrictions for distributors and suppliers
|
||||
# however, admins don't need to be restricted, so, bypassing it for admins
|
||||
cannot :edit_as_producer_only, Spree::Order
|
||||
else
|
||||
can [:index, :read], Country
|
||||
can :create, Order
|
||||
@@ -209,18 +213,20 @@ module Spree
|
||||
managed_product_enterprises.include? variant.supplier
|
||||
end
|
||||
|
||||
can [:admin, :index, :read, :update, :bulk_update, :bulk_reset], VariantOverride do |vo|
|
||||
next false unless vo.hub.present? && vo.variant&.supplier.present?
|
||||
if OpenFoodNetwork::FeatureToggle.enabled?(:inventory, user.enterprises)
|
||||
can [:admin, :index, :read, :update, :bulk_update, :bulk_reset], VariantOverride do |vo|
|
||||
next false unless vo.hub.present? && vo.variant&.supplier.present?
|
||||
|
||||
hub_auth = OpenFoodNetwork::Permissions.new(user).
|
||||
variant_override_hubs.
|
||||
include? vo.hub
|
||||
hub_auth = OpenFoodNetwork::Permissions.new(user).
|
||||
variant_override_hubs.
|
||||
include? vo.hub
|
||||
|
||||
producer_auth = OpenFoodNetwork::Permissions.new(user).
|
||||
variant_override_producers.
|
||||
include? vo.variant.supplier
|
||||
producer_auth = OpenFoodNetwork::Permissions.new(user).
|
||||
variant_override_producers.
|
||||
include? vo.variant.supplier
|
||||
|
||||
hub_auth && producer_auth
|
||||
hub_auth && producer_auth
|
||||
end
|
||||
end
|
||||
|
||||
can [:admin, :create, :update], InventoryItem do |ii|
|
||||
@@ -257,8 +263,13 @@ module Spree
|
||||
end
|
||||
|
||||
def add_order_cycle_management_abilities(user)
|
||||
can [:admin, :index], OrderCycle do |order_cycle|
|
||||
OrderCycle.visible_by(user).include?(order_cycle) ||
|
||||
order_cycle.orders.editable_by_producers(user.enterprises).exists?
|
||||
end
|
||||
|
||||
can [
|
||||
:admin, :index, :read, :edit, :update, :incoming, :outgoing, :checkout_options
|
||||
:read, :edit, :update, :incoming, :outgoing, :checkout_options
|
||||
], OrderCycle do |order_cycle|
|
||||
OrderCycle.visible_by(user).include? order_cycle
|
||||
end
|
||||
@@ -274,8 +285,37 @@ module Spree
|
||||
end
|
||||
|
||||
def add_order_management_abilities(user)
|
||||
can [:index, :create], Spree::Order
|
||||
can [:read, :update, :fire, :resend, :invoice, :print], Spree::Order do |order|
|
||||
can [:manage_order_sections], Spree::Order do |order|
|
||||
user.admin? ||
|
||||
order.distributor.nil? ||
|
||||
user.enterprises.include?(order.distributor) ||
|
||||
order.order_cycle&.coordinated_by?(user)
|
||||
end
|
||||
|
||||
can [:edit_as_producer_only], Spree::Order do |order|
|
||||
cannot?(:manage_order_sections, order) && can_edit_as_producer(order, user)
|
||||
end
|
||||
|
||||
can [:index], Spree::Order do
|
||||
user.admin? ||
|
||||
user.enterprises.any?(&:is_distributor) ||
|
||||
user.enterprises.distributors.where(enable_producers_to_edit_orders: true).exist?
|
||||
end
|
||||
|
||||
can [:create], Spree::Order
|
||||
|
||||
can [:read, :update], Spree::Order do |order|
|
||||
# We allow editing orders with a nil distributor as this state occurs
|
||||
# during the order creation process from the admin backend
|
||||
order.distributor.nil? ||
|
||||
# Enterprise User can access orders that they are a distributor for
|
||||
user.enterprises.include?(order.distributor) ||
|
||||
# Enterprise User can access orders that are placed inside a OC they coordinate
|
||||
order.order_cycle&.coordinated_by?(user) ||
|
||||
can_edit_as_producer(order, user)
|
||||
end
|
||||
|
||||
can [:fire, :resend, :invoice, :print], Spree::Order do |order|
|
||||
# We allow editing orders with a nil distributor as this state occurs
|
||||
# during the order creation process from the admin backend
|
||||
order.distributor.nil? ||
|
||||
@@ -284,22 +324,39 @@ module Spree
|
||||
# Enterprise User can access orders that are placed inside a OC they coordinate
|
||||
order.order_cycle&.coordinated_by?(user)
|
||||
end
|
||||
can [:admin, :bulk_management, :managed, :distribution], Spree::Order do
|
||||
|
||||
can [:admin, :bulk_management], Spree::Order do |order|
|
||||
user.admin? ||
|
||||
user.enterprises.any?(&:is_distributor) ||
|
||||
can_edit_as_producer(order, user)
|
||||
end
|
||||
|
||||
can [:managed, :distribution], Spree::Order do
|
||||
user.admin? || user.enterprises.any?(&:is_distributor)
|
||||
end
|
||||
can [:admin, :index, :create, :show, :poll, :generate], :invoice
|
||||
can [:admin, :visible], Enterprise
|
||||
can [:admin, :index, :create, :update, :destroy], :line_item
|
||||
can [:admin, :index, :create], Spree::LineItem
|
||||
can [:admin, :index, :create], Spree::LineItem do |item|
|
||||
user.admin? ||
|
||||
user.enterprises.any?(&:is_distributor) ||
|
||||
can_edit_as_producer(item.order, user)
|
||||
end
|
||||
can [:destroy, :update], Spree::LineItem do |item|
|
||||
order = item.order
|
||||
user.admin? ||
|
||||
user.enterprises.include?(order.distributor) ||
|
||||
order.order_cycle&.coordinated_by?(user)
|
||||
order.order_cycle&.coordinated_by?(user) ||
|
||||
can_edit_as_producer(order, user)
|
||||
end
|
||||
|
||||
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Shipment do |shipment|
|
||||
user.admin? ||
|
||||
user.enterprises.any?(&:is_distributor) ||
|
||||
can_edit_as_producer(shipment.order, user)
|
||||
end
|
||||
|
||||
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Payment
|
||||
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Shipment
|
||||
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Adjustment
|
||||
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::ReturnAuthorization
|
||||
can [:destroy], Spree::Adjustment do |adjustment|
|
||||
@@ -350,26 +407,35 @@ module Spree
|
||||
can [:admin, :edit, :cancel, :resume], ProxyOrder do |proxy_order|
|
||||
user.enterprises.include?(proxy_order.subscription.shop)
|
||||
end
|
||||
can [:visible], Enterprise
|
||||
end
|
||||
|
||||
def can_edit_order(order, user)
|
||||
def can_edit_as_producer(order, user)
|
||||
return unless order.distributor&.enable_producers_to_edit_orders
|
||||
|
||||
order.variants.any? { |variant| user.enterprises.ids.include?(variant.supplier_id) }
|
||||
end
|
||||
|
||||
def add_manage_line_items_abilities(user)
|
||||
can [:admin, :read, :index, :edit, :update, :bulk_management], Spree::Order do |order|
|
||||
can_edit_order(order, user)
|
||||
can [
|
||||
:admin,
|
||||
:read,
|
||||
:index,
|
||||
:edit,
|
||||
:update,
|
||||
:bulk_management,
|
||||
:edit_as_producer_only
|
||||
], Spree::Order do |order|
|
||||
can_edit_as_producer(order, user)
|
||||
end
|
||||
can [:admin, :index, :create, :destroy, :update], Spree::LineItem do |item|
|
||||
can_edit_order(item.order, user)
|
||||
can_edit_as_producer(item.order, user)
|
||||
end
|
||||
can [:index, :create, :add, :read, :edit, :update], Spree::Shipment do |shipment|
|
||||
can_edit_order(shipment.order, user)
|
||||
can_edit_as_producer(shipment.order, user)
|
||||
end
|
||||
can [:admin, :index], OrderCycle do |order_cycle|
|
||||
can_edit_order(order_cycle.order, user)
|
||||
can_edit_as_producer(order_cycle.order, user)
|
||||
end
|
||||
can [:visible], Enterprise
|
||||
end
|
||||
|
||||
@@ -109,7 +109,7 @@ module Spree
|
||||
}
|
||||
|
||||
scope :editable_by_producers, ->(enterprises_ids) {
|
||||
joins(:variant, order: :distributor).where(
|
||||
joins(variant: :supplier, order: :distributor).where(
|
||||
distributor: { enable_producers_to_edit_orders: true },
|
||||
spree_variants: { supplier_id: enterprises_ids }
|
||||
)
|
||||
|
||||
@@ -9,7 +9,7 @@ module Spree
|
||||
include SetUnusedAddressFields
|
||||
|
||||
searchable_attributes :number, :state, :shipment_state, :payment_state, :distributor_id,
|
||||
:order_cycle_id, :email, :total, :customer_id
|
||||
:order_cycle_id, :email, :total, :customer_id, :distributor_name_alias
|
||||
searchable_associations :shipping_method, :bill_address, :distributor
|
||||
searchable_scopes :complete, :incomplete, :sort_by_billing_address_name_asc,
|
||||
:sort_by_billing_address_name_desc
|
||||
@@ -181,6 +181,11 @@ module Spree
|
||||
scope :by_state, lambda { |state| where(state:) }
|
||||
scope :not_state, lambda { |state| where.not(state:) }
|
||||
|
||||
# This is used to filter line items by the distributor name on BOM page
|
||||
ransacker :distributor_name_alias do
|
||||
Arel.sql("distributor.name")
|
||||
end
|
||||
|
||||
def initialize(*_args)
|
||||
@checkout_processing = nil
|
||||
@manual_shipping_selection = nil
|
||||
|
||||
@@ -194,7 +194,9 @@ module Spree
|
||||
inventory_units.group_by(&:variant).map do |variant, units|
|
||||
states = {}
|
||||
units.group_by(&:state).each { |state, iu| states[state] = iu.count }
|
||||
|
||||
scoper.scope(variant)
|
||||
|
||||
OpenStruct.new(variant:, quantity: units.length, states:)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -102,9 +102,8 @@ module Api
|
||||
end
|
||||
|
||||
def display_value_for_producer(order, value)
|
||||
filter_by_supplier =
|
||||
order.distributor&.enable_producers_to_edit_orders &&
|
||||
options[:current_user]&.can_manage_line_items_in_orders_only?
|
||||
@ability ||= Spree::Ability.new(options[:current_user])
|
||||
filter_by_supplier = @ability.can?(:edit_as_producer_only, order)
|
||||
return value unless filter_by_supplier
|
||||
|
||||
if order.distributor&.show_customer_names_to_suppliers
|
||||
|
||||
@@ -60,6 +60,7 @@ class CartService
|
||||
|
||||
def attempt_cart_add(variant, quantity, max_quantity = nil)
|
||||
scoper.scope(variant)
|
||||
|
||||
return unless valid_variant?(variant)
|
||||
|
||||
cart_add(variant, quantity, max_quantity)
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
|
||||
module OrderCycles
|
||||
class DistributedProductsService # rubocop:disable Metrics/ClassLength
|
||||
def initialize(distributor, order_cycle, customer)
|
||||
def initialize(distributor, order_cycle, customer, **options)
|
||||
@distributor = distributor
|
||||
@order_cycle = order_cycle
|
||||
@customer = customer
|
||||
@options = options
|
||||
end
|
||||
|
||||
def products_relation
|
||||
@@ -26,13 +27,13 @@ module OrderCycles
|
||||
def variants_relation
|
||||
order_cycle.
|
||||
variants_distributed_by(distributor).
|
||||
merge(stocked_variants_and_overrides).
|
||||
merge(variants).
|
||||
select("DISTINCT spree_variants.*")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :distributor, :order_cycle, :customer
|
||||
attr_reader :distributor, :order_cycle, :customer, :options
|
||||
|
||||
def relation_by_sorting
|
||||
query = Spree::Product.where(id: stocked_products)
|
||||
@@ -112,10 +113,18 @@ module OrderCycles
|
||||
def stocked_products
|
||||
order_cycle.
|
||||
variants_distributed_by(distributor).
|
||||
merge(stocked_variants_and_overrides).
|
||||
merge(variants).
|
||||
select("DISTINCT spree_variants.product_id")
|
||||
end
|
||||
|
||||
def variants
|
||||
options[:inventory_enabled] ? stocked_variants_and_overrides : stocked_variants
|
||||
end
|
||||
|
||||
def stocked_variants
|
||||
Spree::Variant.joins(:stock_items).where(query_stock)
|
||||
end
|
||||
|
||||
def stocked_variants_and_overrides
|
||||
stocked_variants = Spree::Variant.
|
||||
joins("LEFT OUTER JOIN variant_overrides ON variant_overrides.variant_id = spree_variants.id
|
||||
@@ -126,6 +135,10 @@ module OrderCycles
|
||||
ProductTagRulesFilterer.new(distributor, customer, stocked_variants).call
|
||||
end
|
||||
|
||||
def query_stock
|
||||
"( #{variant_on_demand} OR #{variant_in_stock} )"
|
||||
end
|
||||
|
||||
def query_stock_with_overrides
|
||||
"( #{variant_not_overriden} AND ( #{variant_on_demand} OR #{variant_in_stock} ) )
|
||||
OR ( #{variant_overriden} AND ( #{override_on_demand} OR #{override_in_stock} ) )
|
||||
|
||||
@@ -52,6 +52,7 @@ module Orders
|
||||
next unless variant = Spree::Variant.find_by(id: li[:variant_id])
|
||||
|
||||
scoper.scope(variant)
|
||||
|
||||
li[:quantity] = stock_limited_quantity(variant.on_demand, variant.on_hand, li[:quantity])
|
||||
li[:price] = variant.price
|
||||
build_item_from(li)
|
||||
|
||||
@@ -21,16 +21,23 @@ module Permissions
|
||||
filtered_orders(orders)
|
||||
end
|
||||
|
||||
def managed_or_coordinated_orders_where_clause
|
||||
Spree::Order.where(
|
||||
managed_orders_where_values.or(coordinated_orders_where_values)
|
||||
)
|
||||
end
|
||||
|
||||
# Any orders that the user can edit
|
||||
def editable_orders
|
||||
orders = if @user.can_manage_line_items_in_orders_only?
|
||||
orders = if @user.admin?
|
||||
# It returns all orders if the user is an admin
|
||||
managed_or_coordinated_orders_where_clause
|
||||
else
|
||||
Spree::Order.joins(:distributor).where(
|
||||
id: produced_orders.select(:id),
|
||||
distributor: { enable_producers_to_edit_orders: true }
|
||||
)
|
||||
else
|
||||
Spree::Order.where(
|
||||
managed_orders_where_values.or(coordinated_orders_where_values)
|
||||
).or(
|
||||
managed_or_coordinated_orders_where_clause
|
||||
)
|
||||
end
|
||||
|
||||
@@ -43,12 +50,19 @@ module Permissions
|
||||
|
||||
# Any line items that I can edit
|
||||
def editable_line_items
|
||||
if @user.can_manage_line_items_in_orders_only?
|
||||
managed_or_coordinated_line_items_where_clause = Spree::LineItem.where(
|
||||
order_id: filtered_orders(managed_or_coordinated_orders_where_clause).select(:id)
|
||||
)
|
||||
|
||||
if @user.admin?
|
||||
# It returns all line_items if the user is an admin
|
||||
managed_or_coordinated_line_items_where_clause
|
||||
else
|
||||
Spree::LineItem.editable_by_producers(
|
||||
@permissions.managed_enterprises.select("enterprises.id")
|
||||
).or(
|
||||
managed_or_coordinated_line_items_where_clause
|
||||
)
|
||||
else
|
||||
Spree::LineItem.where(order_id: editable_orders.select(:id))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -8,11 +8,12 @@ class ProductsRenderer
|
||||
class NoProducts < RuntimeError; end
|
||||
DEFAULT_PER_PAGE = 10
|
||||
|
||||
def initialize(distributor, order_cycle, customer, args = {})
|
||||
def initialize(distributor, order_cycle, customer, args = {}, **options)
|
||||
@distributor = distributor
|
||||
@order_cycle = order_cycle
|
||||
@customer = customer
|
||||
@args = args
|
||||
@options = options
|
||||
end
|
||||
|
||||
def products_json
|
||||
@@ -28,7 +29,7 @@ class ProductsRenderer
|
||||
|
||||
private
|
||||
|
||||
attr_reader :order_cycle, :distributor, :customer, :args
|
||||
attr_reader :order_cycle, :distributor, :customer, :args, :options
|
||||
|
||||
def products
|
||||
return unless order_cycle
|
||||
@@ -40,8 +41,15 @@ class ProductsRenderer
|
||||
distributed_products.products_relation
|
||||
end
|
||||
results = filter(results)
|
||||
# Scope results with variant_overrides
|
||||
paginate(results).each { |product| product_scoper.scope(product) }
|
||||
|
||||
paginated_products = paginate(results)
|
||||
|
||||
if options[:inventory_enabled]
|
||||
# Scope results with variant_overrides
|
||||
paginated_products.each { |product| product_scoper.scope(product) }
|
||||
end
|
||||
|
||||
paginated_products
|
||||
end
|
||||
end
|
||||
|
||||
@@ -106,19 +114,22 @@ class ProductsRenderer
|
||||
end
|
||||
|
||||
def distributed_products
|
||||
OrderCycles::DistributedProductsService.new(distributor, order_cycle, customer)
|
||||
OrderCycles::DistributedProductsService.new(distributor, order_cycle, customer, **options)
|
||||
end
|
||||
|
||||
def variants_for_shop
|
||||
@variants_for_shop ||= begin
|
||||
scoper = OpenFoodNetwork::ScopeVariantToHub.new(distributor)
|
||||
|
||||
# rubocop:disable Rails/FindEach # .each returns an array, .find_each returns nil
|
||||
distributed_products.variants_relation.
|
||||
variants = distributed_products.variants_relation.
|
||||
includes(:default_price, :product).
|
||||
where(product_id: products).
|
||||
each { |v| scoper.scope(v) } # Scope results with variant_overrides
|
||||
# rubocop:enable Rails/FindEach
|
||||
where(product_id: products)
|
||||
|
||||
if options[:inventory_enabled]
|
||||
# Scope results with variant_overrides
|
||||
scoper = OpenFoodNetwork::ScopeVariantToHub.new(distributor)
|
||||
variants = variants.each { |v| scoper.scope(v) }
|
||||
end
|
||||
|
||||
variants
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
- connected_apps_enabled.each do |type|
|
||||
- connected_apps_enabled(enterprise).each do |type|
|
||||
= render partial: "/admin/enterprises/form/connected_apps/#{type}",
|
||||
locals: { enterprise:, connected_app: enterprise.connected_apps.public_send(type).first }
|
||||
|
||||
= render partial: "/admin/enterprises/form/dfc_permissions" if dfc_platforms_available?
|
||||
|
||||
30
app/views/admin/enterprises/form/_dfc_permissions.html.haml
Normal file
30
app/views/admin/enterprises/form/_dfc_permissions.html.haml
Normal file
@@ -0,0 +1,30 @@
|
||||
%script{type: "module", src: "https://cdn.jsdelivr.net/npm/@startinblox/core@latest/dist/index.js"}
|
||||
%script{type: "module"}
|
||||
:plain
|
||||
window.orbit = {
|
||||
client: {
|
||||
name: "Orbit",
|
||||
logo: "https://cdn.startinblox.com/logos/ACME.svg",
|
||||
},
|
||||
components: [],
|
||||
getRoute: (route) => route,
|
||||
getDefaultRoute: () => "",
|
||||
getComponent: () => undefined,
|
||||
getComponentFromRoute: () => undefined,
|
||||
Swal: () => {},
|
||||
defaultRoute: "",
|
||||
federations: {},
|
||||
componentSet: new Set(["routing", "menu", "menu-top", "autoLogin", "solid-permissioning"]),
|
||||
};
|
||||
|
||||
:plain
|
||||
<solid-permissioning
|
||||
data-src="#{DfcProvider::Engine.routes.url_helpers.enterprise_platforms_url(@enterprise.id)}"
|
||||
scopes-uri="https://cdn.startinblox.com/owl/dfc/taxonomies/scopes.jsonld"
|
||||
noRouter
|
||||
auto-lang
|
||||
lang="en"
|
||||
auth-token="#{form_authenticity_token}">
|
||||
</solid-permissioning>
|
||||
|
||||
%script{type: "module", src: "https://cdn.jsdelivr.net/npm/@startinblox/solid-data-permissioning@latest/dist/index.js"}
|
||||
@@ -1,4 +1,6 @@
|
||||
.row{ "ng-controller": "TagRulesCtrl" }
|
||||
= render partial: "admin/json/injection_ams", locals: { ngModule: "admin.tagRules", name: "ruleTypes", json: @tag_rule_types.to_json }
|
||||
|
||||
.row{ "ng-app" => "admin.tagRules", "ng-controller": "TagRulesCtrl" }
|
||||
.eleven.columns.alpha.omega
|
||||
%ofn-sortable{ axis: "y", handle: ".header", items: '.customer_tag', position: "tagGroup.position", "after-sort": "updateRuleCounts()" }
|
||||
.no_tags{ "ng-show": "tagGroups.length == 0" }
|
||||
|
||||
@@ -2,17 +2,18 @@
|
||||
%h3= t('.title')
|
||||
|
||||
= form_for [main_app, :admin, @order_cycle] do |f|
|
||||
.row
|
||||
.three.columns.alpha
|
||||
= f.label "enterprise_preferred_product_selection_from_coordinator_inventory_only", t('admin.order_cycles.edit.choose_products_from')
|
||||
.with-tip{ 'data-powertip' => t('.choose_product_tip', inventory: @order_cycle.coordinator.name) }
|
||||
%a= t('admin.whats_this')
|
||||
.four.columns
|
||||
= f.radio_button :preferred_product_selection_from_coordinator_inventory_only, true
|
||||
= f.label :preferred_product_selection_from_coordinator_inventory_only, t('.preferred_product_selection_from_coordinator_inventory_only_here')
|
||||
.four.columns.omega
|
||||
= f.radio_button :preferred_product_selection_from_coordinator_inventory_only, false
|
||||
= f.label :preferred_product_selection_from_coordinator_inventory_only, t('.preferred_product_selection_from_coordinator_inventory_only_all')
|
||||
- if feature?(:inventory, @order_cycle.coordinator)
|
||||
.row
|
||||
.three.columns.alpha
|
||||
= f.label "enterprise_preferred_product_selection_from_coordinator_inventory_only", t('admin.order_cycles.edit.choose_products_from')
|
||||
.with-tip{ 'data-powertip' => t('.choose_product_tip', inventory: @order_cycle.coordinator.name) }
|
||||
%a= t('admin.whats_this')
|
||||
.four.columns
|
||||
= f.radio_button :preferred_product_selection_from_coordinator_inventory_only, true
|
||||
= f.label :preferred_product_selection_from_coordinator_inventory_only, t('.preferred_product_selection_from_coordinator_inventory_only_here')
|
||||
.four.columns.omega
|
||||
= f.radio_button :preferred_product_selection_from_coordinator_inventory_only, false
|
||||
= f.label :preferred_product_selection_from_coordinator_inventory_only, t('.preferred_product_selection_from_coordinator_inventory_only_all')
|
||||
|
||||
.row
|
||||
.alpha.three.columns
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
|
||||
%h6= t('admin.product_import.index.choose_import_type')
|
||||
%br
|
||||
- options = { "#{t('admin.product_import.index.product_list')}" => :product_list }
|
||||
- options = options.merge("#{t('admin.product_import.index.inventories')}" => :inventories) if feature?(:inventory, spree_current_user.enterprises)
|
||||
= select_tag "settings[import_into]",
|
||||
options_for_select({"#{t('admin.product_import.index.product_list')}" => :product_list, "#{t('admin.product_import.index.inventories')}" => :inventories}),
|
||||
options_for_select(options),
|
||||
{ "data-controller": "tom-select", class: "primary inline no-search", "ng-model": "settings.import_into" }
|
||||
%br
|
||||
%br
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
%i.icon-external-link
|
||||
= t('admin.product_import.index.product_list_template')
|
||||
|
||||
%a.download{href: '/inventory_template.csv'}
|
||||
%i.icon-external-link
|
||||
= t('admin.product_import.index.inventory_template')
|
||||
- if feature?(:inventory, spree_current_user.enterprises)
|
||||
%a.download{href: '/inventory_template.csv'}
|
||||
%i.icon-external-link
|
||||
= t('admin.product_import.index.inventory_template')
|
||||
|
||||
%h5= t('admin.product_import.index.category_values')
|
||||
|
||||
@@ -27,4 +28,4 @@
|
||||
%strong= t('admin.product_import.index.shipping_categories')
|
||||
|
||||
- @shipping_categories.each do |sc|
|
||||
%span.category= sc
|
||||
%span.category= sc
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
= form_with url: bulk_update_admin_products_path, method: :post, id: "products-form",
|
||||
= form_with url: admin_products_bulk_update_path, method: :post, id: "products-form",
|
||||
builder: BulkFormBuilder,
|
||||
html: { data: { 'turbo-frame': "_self",
|
||||
controller: "bulk-form",
|
||||
|
||||
@@ -3,10 +3,7 @@
|
||||
.pagination{ "data-controller": "search" }
|
||||
- if pagy.prev
|
||||
%button.page.prev{ data: { action: 'click->search#changePage', page: pagy.prev } }
|
||||
- if feature?(:admin_style_v3, spree_current_user)
|
||||
%i.icon-chevron-left{ data: { action: 'click->search#changePage', page: pagy.prev } }
|
||||
- else
|
||||
!= pagy_t('pagy.prev')
|
||||
%i.icon-chevron-left{ data: { action: 'click->search#changePage', page: pagy.prev } }
|
||||
- else
|
||||
%button.page.disabled{disabled: "disabled"}!= pagy_t('pagy.prev')
|
||||
|
||||
@@ -22,9 +19,6 @@
|
||||
|
||||
- if pagy.next
|
||||
%button.page.next{ data: { action: 'click->search#changePage', page: pagy.next } }
|
||||
- if feature?(:admin_style_v3, spree_current_user)
|
||||
%i.icon-chevron-right{ data: { action: 'click->search#changePage', page: pagy.next } }
|
||||
- else
|
||||
!= pagy_t('pagy.next')
|
||||
%i.icon-chevron-right{ data: { action: 'click->search#changePage', page: pagy.next } }
|
||||
- else
|
||||
%button.page.disabled.pagination-next{disabled: "disabled"}!= pagy_t('pagy.next')
|
||||
|
||||
28
app/views/checkout/_delivery_details.html.haml
Normal file
28
app/views/checkout/_delivery_details.html.haml
Normal file
@@ -0,0 +1,28 @@
|
||||
%div
|
||||
.summary-subtitle
|
||||
= t("checkout.step3.delivery_details.address")
|
||||
%span
|
||||
= @order.ship_address.firstname
|
||||
= @order.ship_address.lastname
|
||||
%div
|
||||
= @order.ship_address.phone
|
||||
%div
|
||||
= @order.user.email if @order.user
|
||||
%br
|
||||
%div
|
||||
= @order.ship_address.address1
|
||||
- unless @order.ship_address.address2.blank?
|
||||
%div
|
||||
= @order.ship_address.address2
|
||||
%div
|
||||
= @order.ship_address.city
|
||||
%div
|
||||
= @order.ship_address.state
|
||||
%div
|
||||
= @order.ship_address.zipcode
|
||||
%div
|
||||
= @order.ship_address.country
|
||||
- if @order.special_instructions.present?
|
||||
%br
|
||||
%em
|
||||
= @order.special_instructions
|
||||
@@ -91,7 +91,7 @@
|
||||
"data-toggle-show": shipping_method.require_ship_address
|
||||
= shipping_method_form.label shipping_method.id, shipping_method.name, {for: "shipping_method_" + shipping_method.id.to_s }
|
||||
%em.fees= payment_or_shipping_price(shipping_method, @order)
|
||||
- display_ship_address = display_ship_address || (ship_method_is_selected && shipping_method.require_ship_address)
|
||||
- display_ship_address ||= ship_method_is_selected && shipping_method.require_ship_address
|
||||
.checkout-input{"data-shippingmethod-target": "shippingMethodDescription", "data-shippingmethodid": shipping_method.id , style: "display: #{ship_method_is_selected ? 'block' : 'none'}" }
|
||||
#distributor_address.panel
|
||||
- if shipping_method.description.present?
|
||||
|
||||
@@ -11,34 +11,7 @@
|
||||
= @order.shipping_method.name
|
||||
%em.fees= payment_or_shipping_price(@order.shipping_method, @order)
|
||||
.two-columns
|
||||
%div
|
||||
.summary-subtitle
|
||||
= t("checkout.step3.delivery_details.address")
|
||||
%span
|
||||
= @order.ship_address.firstname
|
||||
= @order.ship_address.lastname
|
||||
%div
|
||||
= @order.ship_address.phone
|
||||
%div
|
||||
= @order.user.email if @order.user
|
||||
%br
|
||||
%div
|
||||
= @order.ship_address.address1
|
||||
- unless @order.ship_address.address2.blank?
|
||||
%div
|
||||
= @order.ship_address.address2
|
||||
%div
|
||||
= @order.ship_address.city
|
||||
%div
|
||||
= @order.ship_address.state
|
||||
%div
|
||||
= @order.ship_address.zipcode
|
||||
%div
|
||||
= @order.ship_address.country
|
||||
- if @order.special_instructions.present?
|
||||
%br
|
||||
%em
|
||||
= @order.special_instructions
|
||||
= render "delivery_details" if @order.shipping_method.delivery? || feature?(:hub_address)
|
||||
- if @order.shipping_method.description.present?
|
||||
%div
|
||||
.summary-subtitle
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
- if @order.shipments.any?
|
||||
= render :partial => "spree/admin/orders/shipment", :collection => @order.shipments, :locals => { :order => @order }
|
||||
|
||||
- if spree_current_user.can_manage_orders?
|
||||
- if can?(:manage_order_sections, @order)
|
||||
- if @order.line_items.exists?
|
||||
= render partial: "spree/admin/orders/note", locals: { order: @order }
|
||||
|
||||
|
||||
@@ -47,10 +47,10 @@
|
||||
- if local_assigns[:success]
|
||||
%i.success.icon-ok-sign{"data-controller": "ephemeral"}
|
||||
= render AdminTooltipComponent.new(text: t('spree.admin.orders.index.edit'), link_text: "", link: edit_admin_order_path(order), link_class: "icon_link with-tip icon-edit no-text")
|
||||
- if spree_current_user.can_manage_orders? && order.ready_to_ship?
|
||||
- if can?(:manage_order_sections, order) && order.ready_to_ship?
|
||||
%form
|
||||
= render ShipOrderComponent.new(order: order)
|
||||
= render partial: 'admin/shared/tooltip_button', locals: {button_class: "icon-road icon_link with-tip no-text", reflex_data_id: order.id.to_s, tooltip_text: t('spree.admin.orders.index.ship'), shipment: true}
|
||||
|
||||
- if can?(:update, Spree::Payment) && order.payment_required? && order.pending_payments.reject(&:requires_authorization?).any?
|
||||
- if can?(:manage_order_sections, order) && can?(:update, Spree::Payment) && order.payment_required? && order.pending_payments.reject(&:requires_authorization?).any?
|
||||
= render partial: 'admin/shared/tooltip_button', locals: {button_class: "icon-capture icon_link no-text", button_reflex: "click->Admin::OrdersReflex#capture", reflex_data_id: order.id.to_s, tooltip_text: t('spree.admin.orders.index.capture')}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
- content_for :page_actions do
|
||||
- if can?(:fire, @order)
|
||||
%li= event_links(@order)
|
||||
- if spree_current_user.can_manage_orders?
|
||||
- if can?(:manage_order_sections, @order)
|
||||
= render partial: 'spree/admin/shared/order_links'
|
||||
- if can?(:admin, Spree::Order)
|
||||
%li
|
||||
@@ -14,7 +14,7 @@
|
||||
= t(:back_to_orders_list)
|
||||
|
||||
= render partial: "spree/admin/shared/order_page_title"
|
||||
- if spree_current_user.can_manage_orders?
|
||||
- if can?(:manage_order_sections, @order)
|
||||
= render partial: "spree/admin/shared/order_tabs", locals: { current: 'Order Details' }
|
||||
|
||||
%div
|
||||
@@ -22,7 +22,13 @@
|
||||
|
||||
= admin_inject_shops(@shops, module: 'admin.orders')
|
||||
= admin_inject_order_cycles(@order_cycles)
|
||||
%div{"ng-controller" => "orderCtrl", "ofn-distributor-id" => @order.distributor_id, "ofn-order-cycle-id" => @order.order_cycle_id}
|
||||
%div{
|
||||
"ng-controller" => "orderCtrl",
|
||||
"ofn-distributor-id" => @order.distributor_id,
|
||||
"ofn-order-cycle-id" => @order.order_cycle_id,
|
||||
"ofn-search-variants-as" => (can?(:manage_order_sections, @order) ? 'hub' : 'supplier'),
|
||||
"ofn-order-id" => @order.id,
|
||||
}
|
||||
|
||||
= render :partial => 'add_product' if can?(:update, @order)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
= admin_inject_available_units
|
||||
|
||||
- content_for :page_actions do
|
||||
%li= button_link_to t('admin.products.back_to_products_list'), products_return_to_url(@url_filters), :icon => 'icon-arrow-left'
|
||||
%li= button_link_to t('admin.products.back_to_products_list'), products_return_to_url, :icon => 'icon-arrow-left'
|
||||
%li#new_product_link
|
||||
= button_link_to t(:new_product), new_object_url, { :icon => 'icon-plus', :id => 'admin_new_product' }
|
||||
|
||||
@@ -18,6 +18,6 @@
|
||||
|
||||
= button t(:update), 'icon-refresh'
|
||||
|
||||
= button_link_to t(:cancel), products_return_to_url(@url_filters), icon: 'icon-remove'
|
||||
= button_link_to t(:cancel), products_return_to_url, icon: 'icon-remove'
|
||||
|
||||
#product-preview-modal-container
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
= render 'spree/admin/products/index/header'
|
||||
= render 'spree/admin/products/index/data'
|
||||
= admin_inject_available_units
|
||||
|
||||
%div{ "ng-app": 'ofn.admin', "ng-controller": 'AdminProductEditCtrl', "ng-init": 'initialise()' }
|
||||
|
||||
= render 'spree/admin/products/index/filters'
|
||||
%div{ 'ng-cloak' => true }
|
||||
= render 'spree/admin/products/index/actions'
|
||||
= render 'spree/admin/products/index/indicators'
|
||||
= render 'spree/admin/products/index/products'
|
||||
|
||||
%div{'ng-show' => "!RequestMonitor.loading && products.length > 0" }
|
||||
= render partial: 'admin/shared/angular_pagination'
|
||||
@@ -1,11 +0,0 @@
|
||||
.controls.sixteen.columns.alpha{ 'ng-hide' => 'RequestMonitor.loading || products.length == 0' }
|
||||
.ten.columns.alpha.index-controls
|
||||
.per-page{'ng-show' => '!RequestMonitor.loading && products.length > 0'}
|
||||
%input.per-page-select.ofn-select2{type: 'number', data: 'per_page_options', 'min-search' => 999, 'ng-model' => 'per_page', 'ng-change' => 'fetchProducts()'}
|
||||
|
||||
%span.per-page-feedback
|
||||
{{ 'spree.admin.orders.index.results_found' | t:{number: pagination.results} }}
|
||||
{{ 'spree.admin.orders.index.viewing' | t:{start: ((pagination.page -1) * pagination.per_page) +1, end: ((pagination.page -1) * pagination.per_page) + products.length} }}
|
||||
|
||||
.six.columns.omega
|
||||
%columns-dropdown{ action: "#{controller_name}_#{action_name}" }
|
||||
@@ -1,5 +0,0 @@
|
||||
= admin_inject_producers(@producers)
|
||||
= admin_inject_taxons(@taxons)
|
||||
= admin_inject_tax_categories(@tax_categories)
|
||||
= admin_inject_spree_api_key(@spree_api_key)
|
||||
= admin_inject_column_preferences
|
||||
@@ -1,33 +0,0 @@
|
||||
%fieldset
|
||||
%legend{align: 'center'}= t(:search)
|
||||
|
||||
.filters.sixteen.columns.alpha.omega
|
||||
.quick_search.three.columns.alpha
|
||||
%label{ for: 'quick_filter' }
|
||||
%br
|
||||
%input.quick-search.fullwidth{ name: "quick_filter", type: 'text', placeholder: t('admin.quick_search'), "ng-keypress": "$event.keyCode === 13 && fetchProducts()", "ng-model": 'q.query' }
|
||||
.one.columns
|
||||
.filter_select.three.columns
|
||||
%label{ for: 'producer_filter' }= t 'producer'
|
||||
%br
|
||||
%select.fullwidth{ id: 'producer_filter', "ofn-select2-min-search": 5, "ng-model": 'q.producerFilter', "ng-options": 'producer.id as producer.name for producer in producers' }
|
||||
.filter_select.three.columns
|
||||
%label{ for: 'category_filter' }= t 'category'
|
||||
%br
|
||||
%select.fullwidth{ id: 'category_filter', "ofn-select2-min-search": 5, "ng-model": 'q.categoryFilter', "ng-options": 'taxon.id as taxon.name for taxon in taxons' }
|
||||
.filter_select.three.columns
|
||||
%label{ for: 'import_filter' }= t 'import_date'
|
||||
%br
|
||||
%select.fullwidth{ id: 'import_date_filter', "ofn-select2-min-search": 5, "ng-model": 'q.importDateFilter', "ng-init": "importDates = #{@import_dates}; showLatestImport = #{@show_latest_import}", "ng-options": 'date.id as date.name for date in importDates' }
|
||||
|
||||
.filter_clear.three.columns.omega
|
||||
%label{ for: 'clear_all_filters' }
|
||||
%br
|
||||
%input.fullwidth.red{ :type => 'button', :id => 'clear_all_filters', :value => t('admin.clear_filters'), 'ng-click' => "resetSelectFilters()" }
|
||||
|
||||
.clearfix
|
||||
|
||||
.actions.filter-actions
|
||||
%div
|
||||
%a.button.icon-search{'ng-click' => 'fetchProducts()'}
|
||||
= t(:filter_results)
|
||||
@@ -1,10 +0,0 @@
|
||||
- content_for :page_title do
|
||||
= t('.title')
|
||||
|
||||
- content_for :page_actions do
|
||||
%div{ :class => "toolbar" }
|
||||
%ul{ :class => "actions header-action-links inline-menu" }
|
||||
%li#new_product_link
|
||||
= button_link_to t(:new_product), new_object_url, { :icon => 'icon-plus', :id => 'admin_new_product' }
|
||||
|
||||
= render partial: 'spree/admin/shared/product_sub_menu'
|
||||
@@ -1,14 +0,0 @@
|
||||
.sixteen.columns.alpha#loading{ 'ng-if' => 'RequestMonitor.loading' }
|
||||
= render partial: "components/admin_spinner"
|
||||
%h1
|
||||
= t('.title')
|
||||
|
||||
.sixteen.columns.alpha{ 'ng-show' => '!RequestMonitor.loading && products.length == 0 && q.query.length == 0' }
|
||||
%h1#no_results= t('.no_products')
|
||||
|
||||
.sixteen.columns.alpha{ 'ng-show' => '!RequestMonitor.loading && products.length == 0 && q.query.length != 0' }
|
||||
%h1#no_results
|
||||
= t('.no_results')
|
||||
'
|
||||
{{q.query}}
|
||||
'
|
||||
@@ -1,14 +0,0 @@
|
||||
.sixteen.columns.alpha{ 'ng-hide' => 'RequestMonitor.loading || products.length == 0' }
|
||||
%form{ name: 'bulk_product_form', autocomplete: "off" }
|
||||
%save-bar{ dirty: "bulk_product_form.$dirty", persist: "false" }
|
||||
%input.red{ type: "button", value: t(:save_changes), "ng-click": "submitProducts()", "ng-disabled": "!bulk_product_form.$dirty" }
|
||||
%input{ type: "button", value: t(:close), 'ng-click' => "cancel('#{admin_products_path}')" }
|
||||
|
||||
%table.index#listing_products.bulk
|
||||
|
||||
= render 'spree/admin/products/index/products_head'
|
||||
|
||||
%tbody{ 'ng-repeat' => 'product in products', 'ng-class-even' => "'even'", 'ng-class-odd' => "'odd'" }
|
||||
|
||||
= render 'spree/admin/products/index/products_product'
|
||||
= render 'spree/admin/products/index/products_variant'
|
||||
@@ -1,41 +0,0 @@
|
||||
%colgroup
|
||||
%col.actions
|
||||
%col.image{ "ng-show": 'columns.image.visible' }
|
||||
%col.producer{ "ng-show": 'columns.producer.visible' }
|
||||
%col.sku{ "ng-show": 'columns.sku.visible' }
|
||||
%col.name{ "ng-show": 'columns.name.visible' }
|
||||
%col.unit{ "ng-show": 'columns.unit.visible' }
|
||||
%col.display_as{ "ng-show": 'columns.unit.visible' }
|
||||
%col.price{ "ng-show": 'columns.price.visible' }
|
||||
%col.on_hand{ "ng-show": 'columns.on_hand.visible' }
|
||||
%col.on_demand{ "ng-show": 'columns.on_demand.visible' }
|
||||
%col.category{ "ng-show": 'columns.category.visible' }
|
||||
%col.tax_category{ "ng-show": 'columns.tax_category.visible' }
|
||||
%col.inherits_properties{ "ng-show": 'columns.inherits_properties.visible' }
|
||||
%col.import_date{ "ng-show": 'columns.import_date.visible' }
|
||||
%col.actions
|
||||
%col.actions
|
||||
%col.actions
|
||||
|
||||
%thead
|
||||
%tr{ "ng-controller": "ColumnsCtrl" }
|
||||
%th.left-actions
|
||||
%a{ 'ng-click' => 'toggleShowAllVariants()', :style => 'color: red; cursor: pointer' }
|
||||
= t(:expand_all)
|
||||
%th.image{ 'ng-show' => 'columns.image.visible' }
|
||||
%th.producer{ 'ng-show' => 'columns.producer.visible' }=t('admin.producer')
|
||||
%th.sku{ 'ng-show' => 'columns.sku.visible' }=t('admin.sku')
|
||||
%th.name{ 'ng-show' => 'columns.name.visible' }
|
||||
= render partial: 'spree/admin/shared/sortable_header', locals: {column_name: 'name'}
|
||||
%th.unit{ 'ng-show' => 'columns.unit.visible' }=t('.unit')
|
||||
%th.display_as{ 'ng-show' => 'columns.unit.visible' }=t('.display_as')
|
||||
%th.price{ 'ng-show' => 'columns.price.visible' }=t('admin.price')
|
||||
%th.on_hand{ 'ng-show' => 'columns.on_hand.visible' }=t('admin.on_hand')
|
||||
%th.on_demand{ 'ng-show' => 'columns.on_demand.visible' }=t('admin.on_demand?')
|
||||
%th.category{ 'ng-show' => 'columns.category.visible' }=t('.category')
|
||||
%th.tax_category{ 'ng-show' => 'columns.tax_category.visible' }=t('.tax_category')
|
||||
%th.inherits_properties{ 'ng-show' => 'columns.inherits_properties.visible' }=t('.inherits_properties?')
|
||||
%th.import_date{ 'ng-show' => 'columns.import_date.visible' }=t('.import_date')
|
||||
%th.actions
|
||||
%th.actions
|
||||
%th.actions
|
||||
@@ -1,33 +0,0 @@
|
||||
%tr.product{ :id => "p_{{product.id}}" }
|
||||
%td.left-actions
|
||||
%a{ 'ofn-toggle-variants' => 'true', :class => "view-variants", 'ng-show' => 'hasVariants(product)' }
|
||||
%a{ :class => "add-variant icon-plus-sign", 'ng-click' => "addVariant(product)", 'ng-show' => "!hasVariants(product) && hasUnit(product)" }
|
||||
%td.image{ 'ng-show' => 'columns.image.visible' }
|
||||
%a{class: 'image-modal'}
|
||||
%img{'ng-src' => '{{ product.thumb_url }}'}
|
||||
%td.producer{ 'ng-show' => 'columns.producer.visible' }
|
||||
%td.sku{ 'ng-show' => 'columns.sku.visible' }
|
||||
%input{ 'ng-model' => "product.sku", :name => 'product_sku', 'ofn-track-product' => 'sku', :type => 'text' }
|
||||
%td.name{ 'ng-show' => 'columns.name.visible' }
|
||||
%input{ 'ng-model' => "product.name", :name => 'product_name', 'ofn-track-product' => 'name', :type => 'text' }
|
||||
%td.unit{ 'ng-show' => 'columns.unit.visible' }
|
||||
%td.display_as{ 'ng-show' => 'columns.unit.visible' }
|
||||
%td.price{ 'ng-show' => 'columns.price.visible' }
|
||||
%input{ 'ng-model' => 'product.price', 'ofn-decimal' => :true, :name => 'price', 'ofn-track-product' => 'price', :type => 'text', 'ng-hide' => 'hasVariants(product)' }
|
||||
%td.on_hand{ 'ng-show' => 'columns.on_hand.visible' }
|
||||
%span{ 'ng-bind' => 'product.on_hand', :name => 'on_hand', 'ng-if' => '!hasOnDemandVariants(product) && (hasVariants(product) || product.on_demand)' }
|
||||
%input.field{ 'ng-model' => 'product.on_hand', :name => 'on_hand', 'ofn-track-product' => 'on_hand', 'ng-if' => '!(hasVariants(product) || product.on_demand)', :type => 'number' }
|
||||
%td.on_demand{ 'ng-show' => 'columns.on_demand.visible' }
|
||||
%input.field{ 'ng-model' => 'product.on_demand', :name => 'on_demand', 'ofn-track-product' => 'on_demand', :type => 'checkbox', 'ng-hide' => 'hasVariants(product)' }
|
||||
%td.category{ 'ng-if' => 'columns.category.visible' }
|
||||
%td.tax_category{ 'ng-if' => 'columns.tax_category.visible' }
|
||||
%td.inherits_properties{ 'ng-show' => 'columns.inherits_properties.visible' }
|
||||
%input{ 'ng-model' => 'product.inherits_properties', :name => 'inherits_properties', 'ofn-track-product' => 'inherits_properties', type: "checkbox" }
|
||||
%td.import_date{ 'ng-show' => 'columns.import_date.visible' }
|
||||
%span {{(product.import_date | date:"MMMM dd, yyyy HH:mm") || ""}}
|
||||
%td.actions
|
||||
%a{ 'ng-click' => 'editWarn(product)', :class => "edit-product icon-edit no-text", 'ofn-with-tip' => t(:edit) }
|
||||
%td.actions
|
||||
%a{ 'ng-click' => 'cloneProduct(product)', :class => "clone-product icon-copy no-text", 'ofn-with-tip' => t(:clone) }
|
||||
%td.actions
|
||||
%a{ 'ng-click' => 'deleteProduct(product)', :class => "delete-product icon-trash no-text", 'ofn-with-tip' => t(:remove) }
|
||||
@@ -1,39 +0,0 @@
|
||||
%tr.variant{ :id => "v_{{variant.id}}", 'ng-repeat' => 'variant in product.variants', 'ng-show' => 'DisplayProperties.showVariants(product.id)', 'ng-class-even' => "'even'", 'ng-class-odd' => "'odd'" }
|
||||
%td.left-actions
|
||||
%a{ :class => "variant-item icon-caret-right", 'ng-hide' => "$last" }
|
||||
%a{ :class => "add-variant icon-plus-sign", 'ng-click' => "addVariant(product)", 'ng-show' => "$last", 'ofn-with-tip' => t('.new_variant') }
|
||||
%td{ 'ng-show' => 'columns.image.visible' }
|
||||
%td{ 'ng-show' => 'columns.producer.visible' }
|
||||
%select.fullwidth{ "data-controller": "tom-select", 'ng-model' => 'variant.producer_id', :name => 'producer_id', 'ofn-track-variant' => 'producer_id', 'ng-options' => 'producer.id as producer.name for producer in producers' }
|
||||
%td{ 'ng-show' => 'columns.sku.visible' }
|
||||
%input{ 'ng-model' => "variant.sku", :name => 'variant_sku', 'ofn-track-variant' => 'sku', :type => 'text' }
|
||||
%td{ 'ng-show' => 'columns.name.visible' }
|
||||
%input{ 'ng-model' => 'variant.display_name', :name => 'variant_display_name', 'ofn-track-variant' => 'display_name', :type => 'text', placeholder: "{{ product.name }}" }
|
||||
%td.unit_value{ 'ng-show' => 'columns.unit.visible' }
|
||||
%select.no-search{ "data-controller": "tom-select", 'ng-model' => 'variant.variant_unit_with_scale', :name => 'variant_unit_with_scale', 'ofn-track-variant' => 'variant_unit_with_scale', 'ng-options' => 'unit[1] as unit[0] for unit in variant_unit_options' }
|
||||
%input{ 'ng-model' => 'variant.unit_value_with_description', :name => 'variant_unit_value_with_description', 'ofn-track-variant' => 'unit_value_with_description', :type => 'text', :placeholder => 'value', 'ng-show' => "hasUnit(variant)" }
|
||||
%input{ 'ng-model' => 'variant.variant_unit_name', :name => 'variant_unit_name', 'ofn-track-variant' => 'variant_unit_name', :placeholder => 'unit', 'ng-show' => "variant.variant_unit_with_scale == 'items'", :type => 'text' }
|
||||
%td.display_as{ 'ng-show' => 'columns.unit.visible' }
|
||||
%input{ 'ofn-display-as' => 'variant', 'ng-model' => 'variant.display_as', name: 'variant_display_as', 'ofn-track-variant' => 'display_as', type: 'text', placeholder: '{{ placeholder_text }}' }
|
||||
%td{ 'ng-show' => 'columns.price.visible' }
|
||||
%input{ 'ng-model' => 'variant.price', 'ofn-decimal' => :true, :name => 'variant_price', 'ofn-track-variant' => 'price', :type => 'text' }
|
||||
%td{ 'ng-show' => 'columns.on_hand.visible' }
|
||||
%input.field{ 'ng-model' => 'variant.on_hand', 'ng-change' => 'updateOnHand(product)', :name => 'variant_on_hand', 'ng-if' => '!variant.on_demand', 'ofn-track-variant' => 'on_hand', :type => 'number' }
|
||||
%span{ :name => 'variant_on_hand', 'ng-if' => 'variant.on_demand' }
|
||||
= t(:on_demand)
|
||||
%td{ 'ng-show' => 'columns.on_demand.visible' }
|
||||
%input.field{ 'ng-model' => 'variant.on_demand', :name => 'variant_on_demand', 'ofn-track-variant' => 'on_demand', :type => 'checkbox' }
|
||||
%td{ 'ng-show' => 'columns.category.visible' }
|
||||
%input.fullwidth{ type: 'text', id: "p{{product.id}}_category_id", 'ng-model' => 'variant.category_id', 'ofn-taxon-autocomplete' => '', 'ofn-track-variant' => 'category_id', 'multiple-selection' => 'false', placeholder: 'Category' }
|
||||
%td{ 'ng-show' => 'columns.tax_category.visible' }
|
||||
%select.select2{ name: 'variant_tax_category_id', "ofn-track-variant": 'tax_category_id', "ng-model": 'variant.tax_category_id', "ng-options": 'tax_category.id as tax_category.name for tax_category in tax_categories' }
|
||||
%option{ value: '' }= t(:none)
|
||||
%td{ 'ng-show' => 'columns.inherits_properties.visible' }
|
||||
%td{ 'ng-show' => 'columns.import_date.visible' }
|
||||
%span {{variant.import_date | date:"MMMM dd, yyyy HH:mm"}}
|
||||
%td.actions
|
||||
%a{ 'ng-click' => 'editWarn(product,variant)', :class => "edit-variant icon-edit no-text", 'ng-show' => "variantSaved(variant)", 'ofn-with-tip' => t(:edit) }
|
||||
%td.actions
|
||||
%span.icon-warning-sign{ 'ng-if' => 'variant.variant_overrides_count > 0', 'ofn-with-tip' => "{{ 'spree.admin.products.index.products_variant.variant_has_n_overrides' | t:{n: variant.variant_overrides_count} }}" }
|
||||
%td.actions
|
||||
%a{ 'ng-click' => 'deleteVariant(product,variant)', "ng-class" => '{disabled: product.variants.length < 2}', :class => "delete-variant icon-trash no-text", 'ofn-with-tip' => t(:remove) }
|
||||
@@ -1,3 +0,0 @@
|
||||
.sixteen.columns.alpha{ 'ng-hide' => 'RequestMonitor.loading || products.length == 0', style: "margin-bottom: 10px" }
|
||||
.four.columns.alpha
|
||||
%input.four.columns.alpha{ :type => 'button', :value => t(:save_changes), 'ng-click' => 'submitProducts()'}
|
||||
@@ -14,12 +14,7 @@
|
||||
= " - OFN #{t(:administration)}"
|
||||
|
||||
%link{:href => "https://fonts.googleapis.com/css?family=Open+Sans:400italic,600italic,400,600&subset=latin,cyrillic,greek,vietnamese", :rel => "stylesheet", :type => "text/css"}
|
||||
|
||||
- if feature?(:admin_style_v3, spree_current_user)
|
||||
= stylesheet_pack_tag 'admin-style-v3', media: "screen, print"
|
||||
- else
|
||||
= stylesheet_pack_tag 'admin-styles', media: "screen, print"
|
||||
|
||||
= stylesheet_pack_tag 'admin-style-v3', media: "screen, print"
|
||||
= render "layouts/bugsnag_js"
|
||||
|
||||
- if content_for? :minimal_js
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
- content_for :sub_menu do
|
||||
%ul#sub_nav.inline-menu
|
||||
= tab :products, :products_v3
|
||||
= tab :products, :products_v3, url: admin_products_path
|
||||
= tab :properties
|
||||
= tab :variant_overrides, url: main_app.admin_inventory_path, match_path: '/inventory'
|
||||
= tab :variant_overrides, url: main_app.admin_inventory_path, match_path: '/inventory' if feature?(:inventory, spree_current_user.enterprises)
|
||||
= tab :import, url: main_app.admin_product_import_path, match_path: '/product_import'
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
= tab :overview, label: 'dashboard', url: spree.admin_dashboard_path, icon: 'icon-dashboard'
|
||||
= tab :products, :properties, :inventory, :product_import, :images, :variants, :product_properties, :group_buy_options, :seo, :products_v3, :variant_overrides, url: admin_products_path, icon: 'icon-th-large'
|
||||
= tab :order_cycles, url: main_app.admin_order_cycles_path, icon: 'icon-refresh'
|
||||
= tab :orders, :subscriptions, :customer_details, :adjustments, :payments, :return_authorizations, url: admin_orders_path, icon: 'icon-shopping-cart'
|
||||
= tab :reports, url: main_app.admin_reports_path, icon: 'icon-file'
|
||||
= tab :general_settings, :terms_of_service_files, :mail_methods, :tax_categories, :tax_rates, :tax_settings, :zones, :countries, :states, :payment_methods, :taxons, :shipping_methods, :shipping_categories, :enterprise_fees, :contents, :invoice_settings, :matomo_settings, :stripe_connect_settings, :connected_app_settings, label: 'configuration', icon: 'icon-wrench', url: edit_admin_general_settings_path
|
||||
= tab :overview, label: 'dashboard', url: spree.admin_dashboard_path
|
||||
= tab :products, :properties, :inventory, :product_import, :images, :variants, :product_properties, :group_buy_options, :seo, :products_v3, :variant_overrides, url: admin_products_path
|
||||
= tab :order_cycles, url: main_app.admin_order_cycles_path
|
||||
= tab :orders, :subscriptions, :customer_details, :adjustments, :payments, :return_authorizations, url: admin_orders_path
|
||||
= tab :reports, url: main_app.admin_reports_path
|
||||
= tab :general_settings, :terms_of_service_files, :mail_methods, :tax_categories, :tax_rates, :tax_settings, :zones, :countries, :states, :payment_methods, :taxons, :shipping_methods, :shipping_categories, :enterprise_fees, :contents, :invoice_settings, :matomo_settings, :stripe_connect_settings, :connected_app_settings, label: 'configuration', url: edit_admin_general_settings_path
|
||||
= tab :enterprises, :enterprise_relationships, :vouchers, :oidc_settings, url: main_app.admin_enterprises_path
|
||||
= tab :customers, url: main_app.admin_customers_path
|
||||
= tab :enterprise_groups, url: main_app.admin_enterprise_groups_path, label: 'groups'
|
||||
- if can? :admin, Spree::User
|
||||
= tab(:users, :enterprise_roles, url: spree.admin_users_path, icon: 'icon-user')
|
||||
= tab(:users, :enterprise_roles, url: spree.admin_users_path)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
%thead
|
||||
%tr
|
||||
%th.cart-item-description-header= t(:item)
|
||||
%th.cart-item-price-header.text-right= t(:price)
|
||||
%th.cart-item-price-header= t(:price)
|
||||
%th.text-center.cart-item-quantity-header= t(:qty)
|
||||
%th.cart-item-total-header.text-right= t(:total)
|
||||
%th.cart-item-delete-header
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
= t(".unavailable_item")
|
||||
%br/
|
||||
|
||||
%td.text-right.cart-item-price
|
||||
%td.cart-item-price
|
||||
= line_item.single_display_amount_with_adjustments.to_html
|
||||
%br
|
||||
%span.unit-price
|
||||
|
||||
@@ -1,20 +1,5 @@
|
||||
// import Flatpickr
|
||||
import Flatpickr from "stimulus-flatpickr";
|
||||
import { ar } from "flatpickr/dist/l10n/ar";
|
||||
import { cat } from "flatpickr/dist/l10n/cat";
|
||||
import { cy } from "flatpickr/dist/l10n/cy";
|
||||
import { de } from "flatpickr/dist/l10n/de";
|
||||
import { fi } from "flatpickr/dist/l10n/fi";
|
||||
import { fr } from "flatpickr/dist/l10n/fr";
|
||||
import { it } from "flatpickr/dist/l10n/it";
|
||||
import { nl } from "flatpickr/dist/l10n/nl";
|
||||
import { pl } from "flatpickr/dist/l10n/pl";
|
||||
import { pt } from "flatpickr/dist/l10n/pt";
|
||||
import { ru } from "flatpickr/dist/l10n/ru";
|
||||
import { sv } from "flatpickr/dist/l10n/sv";
|
||||
import { tr } from "flatpickr/dist/l10n/tr";
|
||||
import { en } from "flatpickr/dist/l10n/default.js";
|
||||
import { hu } from "flatpickr/dist/l10n/hu";
|
||||
import ShortcutButtonsPlugin from "shortcut-buttons-flatpickr";
|
||||
import labelPlugin from "flatpickr/dist/plugins/labelPlugin/labelPlugin";
|
||||
|
||||
@@ -24,28 +9,11 @@ export default class extends Flatpickr {
|
||||
*/
|
||||
static values = { enableTime: Boolean, mode: String, defaultDate: String };
|
||||
static targets = ["start", "end"];
|
||||
locales = {
|
||||
ar: ar,
|
||||
cat: cat,
|
||||
cy: cy,
|
||||
de: de,
|
||||
fi: fi,
|
||||
fr: fr,
|
||||
it: it,
|
||||
nl: nl,
|
||||
pl: pl,
|
||||
pt: pt,
|
||||
ru: ru,
|
||||
sv: sv,
|
||||
tr: tr,
|
||||
en: en,
|
||||
hu: hu,
|
||||
};
|
||||
|
||||
initialize() {
|
||||
const datetimepicker = this.enableTimeValue === true;
|
||||
const mode = this.modeValue === "range" ? "range" : "single";
|
||||
// sets your language (you can also set some global setting for all time pickers)
|
||||
// configure flatpickr options (locale set dynamically in connect())
|
||||
this.config = {
|
||||
altInput: true,
|
||||
altFormat: datetimepicker
|
||||
@@ -54,13 +22,18 @@ export default class extends Flatpickr {
|
||||
dateFormat: datetimepicker ? "Y-m-d H:i" : "Y-m-d",
|
||||
enableTime: datetimepicker,
|
||||
time_24hr: datetimepicker,
|
||||
locale: I18n.base_locale,
|
||||
plugins: this.plugins(mode, datetimepicker),
|
||||
mode,
|
||||
};
|
||||
}
|
||||
|
||||
connect() {
|
||||
async connect() {
|
||||
const locale = await this.importFlatpickrLocale(I18n.base_locale);
|
||||
this.config = {
|
||||
...this.config,
|
||||
locale,
|
||||
};
|
||||
|
||||
super.connect();
|
||||
window.addEventListener("flatpickr:change", this.onChangeEvent);
|
||||
window.addEventListener("flatpickr:clear", this.clear);
|
||||
@@ -164,4 +137,16 @@ export default class extends Flatpickr {
|
||||
this.fp.setDate(moment().add(1, "days").startOf("day").format());
|
||||
}
|
||||
}
|
||||
|
||||
async importFlatpickrLocale(localeCode) {
|
||||
// null tells flatpickr to fall back to its built-in english locale
|
||||
if (!localeCode || localeCode === "en") return null;
|
||||
|
||||
try {
|
||||
const localeModule = await import(`flatpickr/dist/l10n/${localeCode}.js`);
|
||||
return localeModule.default?.[localeCode] ?? null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
@import "vendor/assets/stylesheets/normalize";
|
||||
@import "vendor/assets/stylesheets/responsive-tables";
|
||||
@import "vendor/assets/stylesheets/jquery.powertip";
|
||||
@import "~jquery-ui/themes/base/core";
|
||||
@import "~jquery-ui/themes/base/button";
|
||||
@import "~jquery-ui/themes/base/resizable";
|
||||
@import "vendor/assets/stylesheets/jquery-ui-theme";
|
||||
@import "~jquery-ui/themes/base/dialog";
|
||||
@import "../shared/ng-tags-input.min";
|
||||
@import "vendor/assets/stylesheets/select2.css.scss";
|
||||
@import "~flatpickr/dist/flatpickr";
|
||||
@import "~flatpickr/dist/themes/material_blue";
|
||||
@import "~shortcut-buttons-flatpickr/dist/themes/light";
|
||||
|
||||
@import "globals/functions";
|
||||
@import "globals/palette";
|
||||
@import "globals/variables";
|
||||
@import "globals/mixins";
|
||||
|
||||
@import "plugins/font-awesome";
|
||||
|
||||
@import "../shared/variables/layout";
|
||||
@import "../shared/variables/variables";
|
||||
@import "../shared/utilities";
|
||||
@import "shared/typography";
|
||||
@import "shared/tables";
|
||||
@import "shared/icons";
|
||||
@import "shared/forms";
|
||||
@import "shared/layout";
|
||||
@import "shared/scroll_bar";
|
||||
|
||||
@import "../shared/trix";
|
||||
|
||||
@import "plugins/flatpickr-customization";
|
||||
@import "plugins/powertip";
|
||||
@import "plugins/select2";
|
||||
|
||||
@import "sections/orders";
|
||||
@import "sections/products";
|
||||
|
||||
@import "hacks/mozilla";
|
||||
@import "hacks/opera";
|
||||
@import "hacks/ie";
|
||||
|
||||
@import "components/actions";
|
||||
@import "components/alert-box";
|
||||
@import "components/alert_row";
|
||||
@import "components/buttons";
|
||||
@import "components/date-picker";
|
||||
@import "components/dialogs";
|
||||
@import "components/input";
|
||||
@import "components/jquery_dialog";
|
||||
@import "components/messages";
|
||||
@import "components/navigation";
|
||||
@import "components/ng-cloak";
|
||||
@import "components/page_actions";
|
||||
@import "components/pagination";
|
||||
@import "components/per_page_controls";
|
||||
@import "components/product_autocomplete";
|
||||
@import "components/progress";
|
||||
@import "components/save_bar";
|
||||
@import "components/sidebar";
|
||||
@import "components/simple_modal";
|
||||
@import "components/states";
|
||||
@import "components/stripe_connect_button";
|
||||
@import "components/subscriptions_states";
|
||||
@import "components/table-filter";
|
||||
@import "components/table_loading";
|
||||
@import "components/timepicker";
|
||||
@import "components/todo";
|
||||
@import "components/tooltip";
|
||||
@import "components/wizard_progress";
|
||||
|
||||
@import "pages/enterprise_form";
|
||||
@import "pages/subscription_form";
|
||||
@import "pages/subscription_line_items";
|
||||
@import "pages/subscription_review";
|
||||
|
||||
@import "advanced_settings";
|
||||
@import "alert";
|
||||
@import "animations";
|
||||
@import "change_type_form";
|
||||
@import "connected_apps";
|
||||
@import "customers";
|
||||
@import "dashboard_item";
|
||||
@import "dashboard-single-ent";
|
||||
@import "dialog";
|
||||
@import "disabled";
|
||||
@import "dropdown";
|
||||
@import "enterprise_index_panels";
|
||||
@import "enterprises";
|
||||
@import "filters_and_controls";
|
||||
@import "grid";
|
||||
@import "icons";
|
||||
@import "index_panel_buttons";
|
||||
@import "index_panels";
|
||||
@import "modals";
|
||||
@import "offsets";
|
||||
@import "openfoodnetwork";
|
||||
@import "order_cycles";
|
||||
@import "orders";
|
||||
@import "product_import";
|
||||
@import "products";
|
||||
@import "question-mark-tooltip";
|
||||
@import "relationships";
|
||||
@import "reports";
|
||||
@import "select2";
|
||||
@import "sidebar-item";
|
||||
@import "side_menu";
|
||||
@import "tables";
|
||||
@import "tag_rules";
|
||||
@import "terms_of_service_banner";
|
||||
@import "terms_of_service_files";
|
||||
@import "validation";
|
||||
@import "variant_overrides";
|
||||
@import "welcome";
|
||||
|
||||
@import "../shared/question-mark-icon";
|
||||
@import "question-mark-tooltip";
|
||||
|
||||
@import "~tom-select/src/scss/tom-select.default";
|
||||
@import "components/tom_select";
|
||||
|
||||
@import "app/components/modal_component/modal_component";
|
||||
@import "app/webpacker/css/admin/trix.scss";
|
||||
@@ -1,31 +0,0 @@
|
||||
table tbody tr {
|
||||
&.highlight {
|
||||
@each $action in $actions {
|
||||
&.action-#{$action} td {
|
||||
background-color: get-value($actions, $actions-bg-colors, $action);
|
||||
border-color: get-value($actions, $actions-brd-colors, $action);
|
||||
}
|
||||
}
|
||||
|
||||
&.action-remove td,
|
||||
&.action-void td {
|
||||
text-decoration: line-through;
|
||||
|
||||
&.actions {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.before-highlight {
|
||||
@each $action in $actions {
|
||||
&.action-#{$action} td {
|
||||
border-bottom-color: get-value($actions, $actions-brd-colors, $action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
td.actions {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
input[type="submit"],
|
||||
input[type="button"]:not(.trix-button),
|
||||
button:not(.plain):not(.trix-button),
|
||||
.button {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
font-size: 85%;
|
||||
@include border-radius($border-radius);
|
||||
display: inline-block;
|
||||
padding: 8px 15px;
|
||||
border: none;
|
||||
background-color: $color-btn-bg;
|
||||
color: $color-btn-text;
|
||||
text-transform: uppercase;
|
||||
font-weight: 600 !important;
|
||||
|
||||
&:before {
|
||||
font-weight: normal !important;
|
||||
}
|
||||
|
||||
&:visited,
|
||||
&:active,
|
||||
&:focus {
|
||||
color: $color-btn-text;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $color-btn-hover-bg;
|
||||
color: $color-btn-hover-text;
|
||||
}
|
||||
|
||||
&:active:focus {
|
||||
box-shadow: 0 0 8px 0 darken($color-btn-hover-bg, 5) inset;
|
||||
}
|
||||
|
||||
&.fullwidth {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&.secondary {
|
||||
background-color: transparent;
|
||||
border: 1px solid $color-btn-bg;
|
||||
color: $color-btn-bg;
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
background-color: #ebf3fb;
|
||||
}
|
||||
|
||||
&:active:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.badge {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
transform: translateY(-50%);
|
||||
font-size: 10px;
|
||||
text-transform: capitalize;
|
||||
padding: 0px 5px;
|
||||
border-radius: 3px;
|
||||
|
||||
&:before {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&.danger {
|
||||
background-color: $color-warning;
|
||||
}
|
||||
&.success {
|
||||
background-color: $spree-green;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input.red,
|
||||
a.button.red,
|
||||
button.red {
|
||||
background-color: $color-warning;
|
||||
margin-right: 5px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
a.button.red {
|
||||
&:not(:hover) {
|
||||
color: #fff;
|
||||
background-color: $color-warning;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
// scss-lint:disable QualifyingElement
|
||||
|
||||
input.datetimepicker {
|
||||
min-width: 12.9em;
|
||||
}
|
||||
|
||||
.container input[readonly].flatpickr-input,
|
||||
.container input[readonly].datepicker,
|
||||
.container input[readonly].datetimepicker {
|
||||
background-color: $white;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
img.ui-datepicker-trigger {
|
||||
margin-left: -1.75em;
|
||||
position: absolute;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
// scss-lint:enable QualifyingElement
|
||||
@@ -1,76 +0,0 @@
|
||||
.errorExplanation {
|
||||
padding: 10px;
|
||||
border: 1px solid very-light($color-error, 12);
|
||||
background-color: very-light($color-error, 6);
|
||||
border-radius: 3px;
|
||||
color: $color-error;
|
||||
margin-bottom: 15px;
|
||||
|
||||
h2 {
|
||||
font-size: 140%;
|
||||
color: $color-error;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
p {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-position: inside;
|
||||
|
||||
li {
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.flash-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
|
||||
.flash {
|
||||
padding: 18px;
|
||||
text-align: center;
|
||||
font-size: 120%;
|
||||
color: $color-1;
|
||||
font-weight: 600;
|
||||
margin-top: 0;
|
||||
|
||||
&.notice {
|
||||
background-color: rgba($color-notice, 0.8);
|
||||
}
|
||||
&.success {
|
||||
background-color: rgba($color-success, 0.8);
|
||||
}
|
||||
&.error {
|
||||
background-color: rgba($color-error, 0.8);
|
||||
}
|
||||
|
||||
// Adjust heights to fit main layout dimension (header, navbar...)
|
||||
&:nth-child(2) {
|
||||
padding: 24px;
|
||||
}
|
||||
&:nth-child(3) {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: none; /* avoid adding new button on old design */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.notice:not(.flash) {
|
||||
padding: 1rem;
|
||||
margin-bottom: 1.5rem;
|
||||
background-color: $spree-light-blue;
|
||||
border-radius: $border-radius;
|
||||
|
||||
a {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
// Navigation
|
||||
//---------------------------------------------------
|
||||
.inline-menu {
|
||||
margin: 0;
|
||||
-webkit-margin-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
}
|
||||
|
||||
nav.menu {
|
||||
ul {
|
||||
list-style: none;
|
||||
|
||||
li {
|
||||
a {
|
||||
padding: 10px 0;
|
||||
display: block;
|
||||
position: relative;
|
||||
text-align: left;
|
||||
border: 1px solid transparent;
|
||||
text-transform: uppercase;
|
||||
font-weight: 600;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
&.active a {
|
||||
color: $color-2;
|
||||
border-left-width: 0;
|
||||
border-bottom-color: $color-2;
|
||||
}
|
||||
|
||||
&:hover a {
|
||||
color: $color-2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.admin-login-navigation-bar {
|
||||
ul {
|
||||
text-align: right;
|
||||
|
||||
li {
|
||||
padding: 5px 0 5px 10px;
|
||||
text-align: right;
|
||||
font-size: 90%;
|
||||
color: $color-link;
|
||||
margin-top: 8px;
|
||||
|
||||
&.user-logged-in-as {
|
||||
width: 50%;
|
||||
color: $color-body-text;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
i {
|
||||
color: $color-2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#admin-menu {
|
||||
background-color: $color-3;
|
||||
|
||||
ul {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
li {
|
||||
min-width: 90px;
|
||||
flex-grow: 1;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
padding: 25px 5px;
|
||||
color: $color-1 !important;
|
||||
text-transform: uppercase;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
|
||||
i {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $color-2;
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
border-left: 10px solid transparent;
|
||||
border-right: 10px solid transparent;
|
||||
border-top: 5px solid $color-2;
|
||||
bottom: 0px;
|
||||
margin-bottom: -5px;
|
||||
left: 50%;
|
||||
margin-left: -10px;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
span.text {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
a::before {
|
||||
font-weight: normal;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
width: 300px;
|
||||
background-color: $color-3;
|
||||
width: 200px;
|
||||
z-index: 100000;
|
||||
|
||||
> li {
|
||||
width: 200px !important;
|
||||
|
||||
a:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.selected a {
|
||||
@extend a, :hover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#sub-menu {
|
||||
background-color: $color-2;
|
||||
padding-bottom: 0;
|
||||
|
||||
li {
|
||||
a {
|
||||
display: block;
|
||||
padding: 12px 20px;
|
||||
color: $color-1;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
position: relative;
|
||||
font-size: 85%;
|
||||
}
|
||||
|
||||
&.selected a,
|
||||
a:hover {
|
||||
&:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
border-left: 10px solid transparent;
|
||||
border-right: 10px solid transparent;
|
||||
border-top: 5px solid $color-2;
|
||||
bottom: 0px;
|
||||
margin-bottom: -5px;
|
||||
left: 50%;
|
||||
margin-left: -10px;
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#header figure {
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
|
||||
#login-nav {
|
||||
line-height: 1.75em;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
.pagination {
|
||||
text-align: center;
|
||||
margin: 2em 0 1em;
|
||||
padding: 10px 0;
|
||||
|
||||
.page {
|
||||
padding: 5px 8px;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
|
||||
&.current {
|
||||
background-color: $color-2;
|
||||
border-radius: 3px;
|
||||
color: $color-1;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
margin: 0 0.35em;
|
||||
|
||||
&.active {
|
||||
background-color: darken($spree-blue, 15%);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
background-color: $color-btn-disabled-bg;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
// Sidebar
|
||||
//---------------------------------------------------
|
||||
#sidebar {
|
||||
overflow: visible;
|
||||
border-top: 1px solid $color-border;
|
||||
margin-top: 17px;
|
||||
|
||||
.sidebar-title {
|
||||
color: $color-2;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
|
||||
> span {
|
||||
display: inline;
|
||||
background: #fff;
|
||||
padding: 5px 10px;
|
||||
position: relative;
|
||||
top: -14px;
|
||||
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
.ts-wrapper {
|
||||
min-height: initial;
|
||||
}
|
||||
|
||||
.ts-wrapper.multi {
|
||||
.ts-control {
|
||||
box-shadow: none;
|
||||
border-color: $pale-blue;
|
||||
|
||||
&:focus {
|
||||
border-color: $spree-green;
|
||||
}
|
||||
|
||||
[data-value] {
|
||||
text-shadow: none;
|
||||
background-image: none;
|
||||
background-repeat: initial;
|
||||
box-shadow: none;
|
||||
background-color: $spree-blue;
|
||||
}
|
||||
}
|
||||
|
||||
.ts-control > div {
|
||||
border: none;
|
||||
background-color: $spree-blue;
|
||||
}
|
||||
}
|
||||
|
||||
.ts-wrapper.plugin-remove_button .item .remove {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.ts-dropdown {
|
||||
margin-top: 0;
|
||||
|
||||
.option {
|
||||
min-height: 2.25em;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.ts-wrapper.single .ts-control,
|
||||
.ts-dropdown.single {
|
||||
border-color: $color-tbl-border;
|
||||
}
|
||||
|
||||
.ts-control,
|
||||
.ts-wrapper.single.input-active .ts-control {
|
||||
cursor: pointer;
|
||||
padding: 6px 8px;
|
||||
outline: 0 !important;
|
||||
min-height: 2.5em;
|
||||
}
|
||||
|
||||
.ts-wrapper.single .ts-control {
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
.ts-wrapper.inline,
|
||||
.ts-wrapper.inline.input-active {
|
||||
width: fit-content;
|
||||
|
||||
.ts-control {
|
||||
padding-right: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.ts-wrapper.single .ts-control {
|
||||
box-shadow: none;
|
||||
background-image: none;
|
||||
background-color: $white;
|
||||
}
|
||||
|
||||
.ts-wrapper.primary.focus .ts-control,
|
||||
.ts-wrapper.primary .ts-control {
|
||||
background-color: $spree-blue;
|
||||
border-color: $spree-blue;
|
||||
color: $white;
|
||||
|
||||
&:after {
|
||||
border-color: $white transparent transparent transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.ts-wrapper .select-multiple {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ts-wrapper.dropdown-active.primary .ts-control {
|
||||
background-color: $spree-green;
|
||||
border-color: $spree-green;
|
||||
color: $white;
|
||||
|
||||
&:after {
|
||||
border-color: transparent transparent $white transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-input-wrap {
|
||||
padding: 0.2em;
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
@extend [class^="icon-"];
|
||||
@extend .icon-search;
|
||||
|
||||
position: absolute;
|
||||
opacity: 0.4;
|
||||
line-height: 2em;
|
||||
left: 0.75em;
|
||||
}
|
||||
|
||||
.dropdown-input {
|
||||
outline: 0;
|
||||
padding: 4px 6px;
|
||||
border: 1px solid $spree-green;
|
||||
border-radius: 0.3em;
|
||||
padding-left: 1.75em;
|
||||
}
|
||||
}
|
||||
|
||||
.ts-wrapper.no-search {
|
||||
.dropdown-input-wrap {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.ts-dropdown .create:hover,
|
||||
.ts-dropdown #admin-menu li.selected a.create,
|
||||
#admin-menu li.selected .ts-dropdown a.create,
|
||||
.ts-dropdown .option:hover,
|
||||
.ts-dropdown #admin-menu li.selected a.option,
|
||||
#admin-menu li.selected .ts-dropdown a.option,
|
||||
.ts-dropdown .active {
|
||||
background-color: $spree-blue;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.ts-dropdown [data-selectable] .highlight {
|
||||
background: rgba(149, 180, 255, 0.26);
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
// -------------------------------------------------------------
|
||||
// Variables used in all other files
|
||||
//--------------------------------------------------------------
|
||||
|
||||
// Fonts
|
||||
//--------------------------------------------------------------
|
||||
$base-font-family: "Open Sans", "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
|
||||
|
||||
// Colors
|
||||
//--------------------------------------------------------------
|
||||
|
||||
// Body base colors
|
||||
$color-body-bg: $color-1 !default;
|
||||
$color-body-text: $color-4 !default;
|
||||
$color-headers: $color-4 !default;
|
||||
$color-link: $color-3 !default;
|
||||
$color-link-hover: $color-2 !default;
|
||||
$color-link-active: $color-2 !default;
|
||||
$color-link-focus: $color-2 !default;
|
||||
$color-link-visited: $color-3 !default;
|
||||
$color-border: very-light($color-3, 12) !default;
|
||||
|
||||
// Basic flash colors
|
||||
$color-success: $color-2 !default;
|
||||
$color-notice: $color-6 !default;
|
||||
$color-warning: $color-5 !default;
|
||||
$color-error: $color-5 !default;
|
||||
|
||||
// Table colors
|
||||
$color-tbl-odd: $color-1 !default;
|
||||
$color-tbl-even: very-light($color-3, 4) !default;
|
||||
$color-tbl-thead: very-light($color-3, 4) !default;
|
||||
$color-tbl-border: $pale-blue !default;
|
||||
|
||||
// Button colors
|
||||
$color-btn-bg: $color-3 !default;
|
||||
$color-btn-text: $color-1 !default;
|
||||
$color-btn-hover-bg: $color-2 !default;
|
||||
$color-btn-hover-text: $color-1 !default;
|
||||
$color-btn-disabled-bg: $light-grey !default;
|
||||
|
||||
// Actions colors
|
||||
$color-action-edit-bg: very-light($color-success, 5 ) !default;
|
||||
$color-action-edit-brd: very-light($color-success, 20 ) !default;
|
||||
$color-action-clone-bg: very-light($color-notice, 5 ) !default;
|
||||
$color-action-clone-brd: very-light($color-notice, 15 ) !default;
|
||||
$color-action-remove-bg: very-light($color-error, 5 ) !default;
|
||||
$color-action-remove-brd: very-light($color-error, 10 ) !default;
|
||||
$color-action-void-bg: very-light($color-error, 10 ) !default;
|
||||
$color-action-void-brd: very-light($color-error, 20 ) !default;
|
||||
$color-action-cancel-bg: very-light($color-notice, 10 ) !default;
|
||||
$color-action-cancel-brd: very-light($color-notice, 20 ) !default;
|
||||
$color-action-capture-bg: very-light($color-success, 5 ) !default;
|
||||
$color-action-capture-brd: very-light($color-success, 20 ) !default;
|
||||
$color-action-save-bg: very-light($color-success, 5 ) !default;
|
||||
$color-action-save-brd: very-light($color-success, 20 ) !default;
|
||||
$color-action-mail-bg: very-light($color-success, 5 ) !default;
|
||||
$color-action-mail-brd: very-light($color-success, 20 ) !default;
|
||||
|
||||
// Select2 select field colors
|
||||
$color-sel-bg: $color-3 !default;
|
||||
$color-sel-text: $color-1 !default;
|
||||
$color-sel-hover-bg: $color-2 !default;
|
||||
$color-sel-hover-text: $color-1 !default;
|
||||
|
||||
// Text inputs colors
|
||||
$color-txt-brd: $color-border !default;
|
||||
$color-txt-text: $color-3 !default;
|
||||
$color-txt-hover-brd: $color-2 !default;
|
||||
$vpadding-txt: 7px;
|
||||
$hpadding-txt: 10px;
|
||||
|
||||
// Modal colors
|
||||
$color-modal-close-btn: $color-5 !default;
|
||||
$color-modal-close-btn-hover: darken($color-5, 5%) !default;
|
||||
|
||||
// States label colors
|
||||
$color-ste-complete-bg: $color-success !default;
|
||||
$color-ste-complete-text: $color-1 !default;
|
||||
$color-ste-completed-bg: $color-success !default;
|
||||
$color-ste-completed-text: $color-1 !default;
|
||||
$color-ste-sold-bg: $color-success !default;
|
||||
$color-ste-sold-text: $color-1 !default;
|
||||
$color-ste-pending-bg: $color-notice !default;
|
||||
$color-ste-pending-text: $color-1 !default;
|
||||
$color-ste-requires_authorization-bg: $color-notice !default;
|
||||
$color-ste-requires_authorization-text: $color-1 !default;
|
||||
$color-ste-awaiting_return-bg: $color-notice !default;
|
||||
$color-ste-awaiting_return-text: $color-1 !default;
|
||||
$color-ste-returned-bg: $color-notice !default;
|
||||
$color-ste-returned-text: $color-1 !default;
|
||||
$color-ste-credit_owed-bg: $color-notice !default;
|
||||
$color-ste-credit_owed-text: $color-1 !default;
|
||||
$color-ste-paid-bg: $color-success !default;
|
||||
$color-ste-paid-text: $color-1 !default;
|
||||
$color-ste-shipped-bg: $color-success !default;
|
||||
$color-ste-shipped-text: $color-1 !default;
|
||||
$color-ste-balance_due-bg: $color-notice !default;
|
||||
$color-ste-balance_due-text: $color-1 !default;
|
||||
$color-ste-backorder-bg: $color-notice !default;
|
||||
$color-ste-backorder-text: $color-1 !default;
|
||||
$color-ste-none-bg: $color-error !default;
|
||||
$color-ste-none-text: $color-1 !default;
|
||||
$color-ste-ready-bg: $color-success !default;
|
||||
$color-ste-ready-text: $color-1 !default;
|
||||
$color-ste-void-bg: $color-error !default;
|
||||
$color-ste-void-text: $color-1 !default;
|
||||
$color-ste-canceled-bg: $color-error !default;
|
||||
$color-ste-canceled-text: $color-1 !default;
|
||||
$color-ste-address-bg: $color-error !default;
|
||||
$color-ste-address-text: $color-1 !default;
|
||||
$color-ste-checkout-bg: $color-notice !default;
|
||||
$color-ste-checkout-text: $color-1 !default;
|
||||
$color-ste-cart-bg: $color-notice !default;
|
||||
$color-ste-cart-text: $color-1 !default;
|
||||
$color-ste-payment-bg: $color-error !default;
|
||||
$color-ste-payment-text: $color-1 !default;
|
||||
$color-ste-delivery-bg: $color-success !default;
|
||||
$color-ste-delivery-text: $color-1 !default;
|
||||
$color-ste-confirmation-bg: $color-error !default;
|
||||
$color-ste-confirmation-text: $color-1 !default;
|
||||
$color-ste-active-bg: $color-success !default;
|
||||
$color-ste-active-text: $color-1 !default;
|
||||
$color-ste-inactive-bg: $color-notice !default;
|
||||
$color-ste-inactive-text: $color-1 !default;
|
||||
|
||||
// Available states
|
||||
$states: completed, complete, sold, pending, awaiting_return, returned, credit_owed, paid, shipped, balance_due, backorder, checkout, cart, address, delivery, payment, confirmation, canceled, ready, void, requires_authorization, active, inactive !default;
|
||||
$states-bg-colors: $color-ste-completed-bg, $color-ste-complete-bg, $color-ste-sold-bg, $color-ste-pending-bg, $color-ste-awaiting_return-bg, $color-ste-returned-bg, $color-ste-credit_owed-bg, $color-ste-paid-bg, $color-ste-shipped-bg, $color-ste-balance_due-bg, $color-ste-backorder-bg, $color-ste-checkout-bg, $color-ste-cart-bg, $color-ste-address-bg, $color-ste-delivery-bg, $color-ste-payment-bg, $color-ste-confirmation-bg, $color-ste-canceled-bg, $color-ste-ready-bg, $color-ste-void-bg, $color-ste-requires_authorization-bg, $color-ste-active-bg, $color-ste-inactive-bg !default;
|
||||
$states-text-colors: $color-ste-completed-text, $color-ste-complete-text, $color-ste-sold-text, $color-ste-pending-text, $color-ste-awaiting_return-text, $color-ste-returned-text, $color-ste-credit_owed-text, $color-ste-paid-text, $color-ste-shipped-text, $color-ste-balance_due-text, $color-ste-backorder-text, $color-ste-checkout-text, $color-ste-cart-text, $color-ste-address-text, $color-ste-delivery-text, $color-ste-payment-text, $color-ste-confirmation-text, $color-ste-canceled-text, $color-ste-ready-text, $color-ste-void-text, $color-ste-requires_authorization-text, $color-ste-active-text, $color-ste-inactive-text !default;
|
||||
|
||||
// Available actions
|
||||
$actions: edit, clone, remove, void, capture, save, cancel, mail !default;
|
||||
$actions-bg-colors: $color-action-edit-bg, $color-action-clone-bg, $color-action-remove-bg, $color-action-void-bg, $color-action-capture-bg, $color-action-save-bg, $color-action-cancel-bg, $color-action-mail-bg !default;
|
||||
$actions-brd-colors: $color-action-edit-brd, $color-action-clone-brd, $color-action-remove-brd, $color-action-void-brd, $color-action-capture-brd, $color-action-save-brd, $color-action-cancel-brd, $color-action-mail-brd !default;
|
||||
|
||||
// Sizes
|
||||
//--------------------------------------------------------------
|
||||
$body-font-size: 13px !default;
|
||||
|
||||
$h6-size: $body-font-size + 2 !default;
|
||||
$h5-size: $h6-size + 2 !default;
|
||||
$h4-size: $h5-size + 2 !default;
|
||||
$h3-size: $h4-size + 2 !default;
|
||||
$h2-size: $h3-size + 2 !default;
|
||||
$h1-size: $h2-size + 2 !default;
|
||||
|
||||
$border-radius: 3px !default;
|
||||
$border-input: 1px solid #2e3132; // Copied over from admin_v3 variables as a temporary solution
|
||||
|
||||
$font-weight-bold: 600 !default;
|
||||
$font-weight-normal: 400 !default;
|
||||
|
||||
// z-index
|
||||
//--------------------------------------------------------------
|
||||
$tos-banner-z-index: 102;
|
||||
@@ -1,68 +0,0 @@
|
||||
$background-grey: #eceef1;
|
||||
$background-blue: $color-3;
|
||||
|
||||
// scss-lint:disable SelectorFormat
|
||||
|
||||
.flatpickr-calendar {
|
||||
border-radius: 0;
|
||||
|
||||
// Disable animation
|
||||
&.animate.open {
|
||||
animation: none;
|
||||
}
|
||||
|
||||
&.arrowBottom::after {
|
||||
border-top-color: $background-grey;
|
||||
}
|
||||
|
||||
&.arrowTop::after {
|
||||
border-bottom-color: $background-blue;
|
||||
}
|
||||
|
||||
.flatpickr-months .flatpickr-month {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.flatpickr-months .flatpickr-month,
|
||||
.flatpickr-current-month .flatpickr-monthDropdown-months {
|
||||
background: $background-blue;
|
||||
}
|
||||
|
||||
.flatpickr-weekdays {
|
||||
background: $background-blue;
|
||||
|
||||
.flatpickr-weekday {
|
||||
background: $background-blue;
|
||||
}
|
||||
}
|
||||
|
||||
.flatpickr-day.selected,
|
||||
.flatpickr-day.startRange,
|
||||
.flatpickr-day.endRange,
|
||||
.flatpickr-day.selected.inRange,
|
||||
.flatpickr-day.startRange.inRange,
|
||||
.flatpickr-day.endRange.inRange,
|
||||
.flatpickr-day.selected:focus,
|
||||
.flatpickr-day.startRange:focus,
|
||||
.flatpickr-day.endRange:focus,
|
||||
.flatpickr-day.selected:hover,
|
||||
.flatpickr-day.startRange:hover,
|
||||
.flatpickr-day.endRange:hover,
|
||||
.flatpickr-day.selected.prevMonthDay,
|
||||
.flatpickr-day.startRange.prevMonthDay,
|
||||
.flatpickr-day.endRange.prevMonthDay,
|
||||
.flatpickr-day.selected.nextMonthDay,
|
||||
.flatpickr-day.startRange.nextMonthDay,
|
||||
.flatpickr-day.endRange.nextMonthDay {
|
||||
background: $background-blue;
|
||||
border-color: $background-blue;
|
||||
}
|
||||
}
|
||||
|
||||
// scss-lint:enable SelectorFormat
|
||||
|
||||
// customization for shortcut-buttons
|
||||
.shortcut-buttons-flatpickr-wrapper > .shortcut-buttons-flatpickr-buttons {
|
||||
justify-content: space-between;
|
||||
flex-grow: 1;
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
#powerTip {
|
||||
background-color: $color-3;
|
||||
padding: 5px 15px;
|
||||
@include border-radius($border-radius);
|
||||
|
||||
&.n:before,
|
||||
&.ne:before,
|
||||
&.nw:before {
|
||||
border-top-width: 5px;
|
||||
border-top-color: $color-3;
|
||||
bottom: -5px;
|
||||
}
|
||||
|
||||
&.e:before {
|
||||
border-right-width: 5px;
|
||||
border-right-color: $color-3;
|
||||
left: -5px;
|
||||
}
|
||||
&.s:before,
|
||||
&.se:before,
|
||||
&.sw:before {
|
||||
border-bottom-width: 5px;
|
||||
border-bottom-color: $color-3;
|
||||
top: -5px;
|
||||
}
|
||||
&.w:before {
|
||||
border-left-width: 5px;
|
||||
border-left-color: $color-3;
|
||||
right: -5px;
|
||||
}
|
||||
&.ne:before,
|
||||
&.se:before {
|
||||
border-right-width: 5px;
|
||||
border-right-color: $color-3;
|
||||
left: -5px;
|
||||
}
|
||||
&.nw:before,
|
||||
&.sw:before {
|
||||
border-left-width: 5px;
|
||||
border-right-color: $color-3;
|
||||
right: -5px;
|
||||
}
|
||||
|
||||
&.clone,
|
||||
&.yellow,
|
||||
&.cancel {
|
||||
background-color: $color-notice;
|
||||
|
||||
&.n:before,
|
||||
&.ne:before,
|
||||
&.nw:before {
|
||||
border-top-color: $color-notice;
|
||||
}
|
||||
&.e:before,
|
||||
&.nw:before,
|
||||
&.sw:before {
|
||||
border-right-color: $color-notice;
|
||||
}
|
||||
&.s:before,
|
||||
&.se:before,
|
||||
&.sw:before {
|
||||
border-bottom-color: $color-notice;
|
||||
}
|
||||
&.w:before {
|
||||
border-left-color: $color-notice;
|
||||
}
|
||||
}
|
||||
&.edit,
|
||||
&.green,
|
||||
&.capture,
|
||||
&.save,
|
||||
&.add {
|
||||
background-color: $color-success;
|
||||
|
||||
&.n:before,
|
||||
&.ne:before,
|
||||
&.nw:before {
|
||||
border-top-color: $color-success;
|
||||
}
|
||||
&.e:before,
|
||||
&.nw:before,
|
||||
&.sw:before {
|
||||
border-right-color: $color-success;
|
||||
}
|
||||
&.s:before,
|
||||
&.se:before,
|
||||
&.sw:before {
|
||||
border-bottom-color: $color-success;
|
||||
}
|
||||
&.w:before {
|
||||
border-left-color: $color-success;
|
||||
}
|
||||
}
|
||||
&.remove,
|
||||
&.red,
|
||||
&.void {
|
||||
background-color: $color-error;
|
||||
|
||||
&.n:before,
|
||||
&.ne:before,
|
||||
&.nw:before {
|
||||
border-top-color: $color-error;
|
||||
}
|
||||
&.e:before,
|
||||
&.nw:before,
|
||||
&.sw:before {
|
||||
border-right-color: $color-error;
|
||||
}
|
||||
&.s:before,
|
||||
&.se:before,
|
||||
&.sw:before {
|
||||
border-bottom-color: $color-error;
|
||||
}
|
||||
&.w:before {
|
||||
border-left-color: $color-error;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
// Customize orders filter
|
||||
.admin-orders-index-search {
|
||||
select[data-placeholder="Status"] {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.select2-container {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
// Order-total
|
||||
.order-details-total {
|
||||
text-align: center;
|
||||
|
||||
.order-total {
|
||||
font-size: 35px;
|
||||
font-weight: 600;
|
||||
color: $color-success;
|
||||
}
|
||||
}
|
||||
|
||||
.admin-order-form-fields {
|
||||
legend.stock-location {
|
||||
color: $color-body-text;
|
||||
|
||||
.shipment-number {
|
||||
color: $color-success;
|
||||
}
|
||||
.stock-location-name {
|
||||
color: $color-success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.insufficient-stock-items {
|
||||
legend {
|
||||
color: $color-error;
|
||||
}
|
||||
|
||||
table tr:last-child th {
|
||||
border-bottom: 1px solid $color-tbl-border;
|
||||
}
|
||||
}
|
||||
|
||||
// Customize orduct add fieldset
|
||||
#add-line-item {
|
||||
fieldset {
|
||||
padding: 10px 0;
|
||||
|
||||
.field {
|
||||
margin-bottom: 0;
|
||||
|
||||
input[type="text"],
|
||||
input[type="number"] {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.actions {
|
||||
.button {
|
||||
margin-top: 28px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,261 +0,0 @@
|
||||
$text-inputs: "input[type=text], input[type=password], input[type=email], input[type=url], input[type=tel]";
|
||||
|
||||
#{$text-inputs},
|
||||
input[type="date"],
|
||||
input[type="datetime"],
|
||||
input[type="time"],
|
||||
input[type="number"],
|
||||
textarea,
|
||||
fieldset {
|
||||
@include border-radius($border-radius);
|
||||
padding: $vpadding-txt $hpadding-txt;
|
||||
border: 1px solid $color-txt-brd;
|
||||
color: $color-txt-text;
|
||||
font-size: 90%;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: $color-txt-hover-brd;
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
line-height: 19px;
|
||||
}
|
||||
|
||||
.fullwidth {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
label {
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
font-size: 85%;
|
||||
display: inline;
|
||||
margin-bottom: 5px;
|
||||
color: $color-4;
|
||||
|
||||
&.inline {
|
||||
display: inline-block !important;
|
||||
}
|
||||
|
||||
&.block {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
|
||||
.label-block label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
span.info {
|
||||
font-style: italic;
|
||||
font-size: 85%;
|
||||
color: lighten($color-body-text, 15);
|
||||
display: block;
|
||||
line-height: 20px;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.field {
|
||||
padding: 10px 0;
|
||||
|
||||
&.checkbox {
|
||||
min-height: 70px;
|
||||
|
||||
input[type="checkbox"] {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
label {
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
border-top: 1px solid $color-border;
|
||||
list-style: none;
|
||||
padding-top: 5px;
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
padding-right: 10px;
|
||||
|
||||
label {
|
||||
font-weight: normal;
|
||||
text-transform: none;
|
||||
}
|
||||
&.white-space-nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Errors described by default form builder
|
||||
.field_with_errors {
|
||||
label {
|
||||
color: $color-error;
|
||||
}
|
||||
|
||||
input {
|
||||
border-color: $color-error;
|
||||
}
|
||||
}
|
||||
// Errors described by Spree::Admin::BaseHelper
|
||||
.formError {
|
||||
color: $color-error;
|
||||
font-style: italic;
|
||||
font-size: 85%;
|
||||
}
|
||||
}
|
||||
|
||||
fieldset {
|
||||
box-shadow: none;
|
||||
box-sizing: border-box;
|
||||
border-color: $color-border;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
position: relative;
|
||||
margin-bottom: 35px;
|
||||
padding: 10px 0 15px 0;
|
||||
background-color: transparent;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
border-radius: 0;
|
||||
|
||||
&.no-border-bottom {
|
||||
border-bottom: none;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&.no-border-top {
|
||||
border-top: none;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
background-color: $color-1;
|
||||
color: $color-2;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
padding: 8px 15px;
|
||||
margin: 0 auto;
|
||||
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
i {
|
||||
color: $color-link;
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
color: lighten($color-body-text, 8);
|
||||
}
|
||||
|
||||
.filter-actions {
|
||||
margin-bottom: -32px;
|
||||
margin-top: 15px;
|
||||
text-align: center;
|
||||
|
||||
form {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
button,
|
||||
.button,
|
||||
input[type="submit"],
|
||||
input[type="button"],
|
||||
span.or {
|
||||
@include border-radius($border-radius);
|
||||
|
||||
-webkit-box-shadow: 0 0 0 15px $color-1;
|
||||
-moz-box-shadow: 0 0 0 15px $color-1;
|
||||
-ms-box-shadow: 0 0 0 15px $color-1;
|
||||
-o-box-shadow: 0 0 0 15px $color-1;
|
||||
box-shadow: 0 0 0 15px $color-1;
|
||||
|
||||
&:hover {
|
||||
border-color: $color-1;
|
||||
}
|
||||
|
||||
&:first-of-type {
|
||||
margin-right: 1.25em;
|
||||
}
|
||||
}
|
||||
|
||||
span.or {
|
||||
background-color: $color-1;
|
||||
border-width: 5px;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
position: relative;
|
||||
|
||||
-webkit-box-shadow: 0 0 0 5px $color-1;
|
||||
-moz-box-shadow: 0 0 0 5px $color-1;
|
||||
-ms-box-shadow: 0 0 0 5px $color-1;
|
||||
-o-box-shadow: 0 0 0 5px $color-1;
|
||||
box-shadow: 0 0 0 5px $color-1;
|
||||
}
|
||||
}
|
||||
|
||||
&.labels-inline {
|
||||
.field {
|
||||
margin-bottom: 0;
|
||||
display: table;
|
||||
width: 100%;
|
||||
|
||||
label,
|
||||
input {
|
||||
display: table-cell !important;
|
||||
}
|
||||
input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&.checkbox {
|
||||
input {
|
||||
width: auto !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.actions {
|
||||
padding: 0;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-buttons {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
select {
|
||||
@extend input, [type="text"];
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.inline-checkbox {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin-top: 3px;
|
||||
|
||||
input,
|
||||
label {
|
||||
cursor: pointer;
|
||||
}
|
||||
label {
|
||||
margin: 0;
|
||||
padding-left: 0.4rem;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
// Some fixes for fontwesome stylesheets
|
||||
[class^="icon-"], [class*=" icon-"] {
|
||||
&:before {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
&.button, &.icon_link {
|
||||
width: auto;
|
||||
|
||||
&:before {
|
||||
padding-top: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon-email:before { @extend .icon-envelope, :before; }
|
||||
.icon-resend_authorization_email:before { @extend .icon-envelope, :before; }
|
||||
.icon-resume:before { @extend .icon-refresh, :before; }
|
||||
|
||||
.icon-cancel:before,
|
||||
.icon-void:before { @extend .icon-remove, :before; }
|
||||
|
||||
.icon-capture,
|
||||
.icon-capture_and_complete_order { @extend .icon-ok }
|
||||
.icon-credit:before { @extend .icon-ok, :before ; }
|
||||
@@ -1,134 +0,0 @@
|
||||
// Basics
|
||||
//---------------------------------------------------
|
||||
* {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.admin {
|
||||
&__section-header {
|
||||
padding: 15px 0;
|
||||
background-color: very-light($color-3, 4);
|
||||
border-bottom: 1px solid $color-border;
|
||||
|
||||
.ofn-drop-down {
|
||||
border: 0;
|
||||
background-color: $spree-blue;
|
||||
color: $color-1;
|
||||
float: none;
|
||||
margin-left: 3px;
|
||||
&:hover,
|
||||
&.expanded {
|
||||
border: 0;
|
||||
color: $color-1;
|
||||
}
|
||||
}
|
||||
|
||||
&__content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
@media all and (min-width: $tablet_breakpoint) {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
&__title {
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
@media all and (min-width: $tablet_breakpoint) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__actions {
|
||||
display: flex;
|
||||
flex: 1 0 auto;
|
||||
align-items: center;
|
||||
list-style: none;
|
||||
@media all and (min-width: $tablet_breakpoint) {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
> li {
|
||||
display: flex;
|
||||
margin-right: 10px;
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.float-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.float-left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.mr-0 {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
|
||||
.ml-0 {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
@media print {
|
||||
.print-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
// Header
|
||||
//---------------------------------------------------
|
||||
#header {
|
||||
background-color: $color-1;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
#logo {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
i {
|
||||
color: $color-2;
|
||||
}
|
||||
}
|
||||
|
||||
// Content
|
||||
//---------------------------------------------------
|
||||
#content {
|
||||
background-color: $color-1;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
padding: 0;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
// Footer
|
||||
//---------------------------------------------------
|
||||
#footer {
|
||||
margin-top: 15px;
|
||||
border-top: 1px solid $color-border;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
@media print {
|
||||
header,
|
||||
nav {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -1,208 +0,0 @@
|
||||
table {
|
||||
width: 100%;
|
||||
margin-bottom: 15px;
|
||||
border-collapse: separate;
|
||||
|
||||
th, td {
|
||||
padding: 7px 5px;
|
||||
border-right: 1px solid $color-border;
|
||||
border-bottom: 1px solid $color-border;
|
||||
vertical-align: middle;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
img {
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
border-left: 1px solid $color-border;
|
||||
}
|
||||
|
||||
a {
|
||||
border-bottom: 1px dotted lighten($color-link, 10);
|
||||
|
||||
&:hover {
|
||||
border-color: lighten($color-link-hover, 10);
|
||||
}
|
||||
}
|
||||
|
||||
.handle {
|
||||
display: block !important;
|
||||
text-align: center;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
&.actions {
|
||||
background-color: transparent;
|
||||
border: none !important;
|
||||
text-align: center;
|
||||
|
||||
span.text {
|
||||
font-size: $body-font-size;
|
||||
}
|
||||
|
||||
[class*='icon-'].no-text {
|
||||
font-size: 120%;
|
||||
background-color: very-light($color-3);
|
||||
border: 1px solid $color-border;
|
||||
border-radius: 15px;
|
||||
width: 29px;
|
||||
height: 29px;
|
||||
display: inline-block;
|
||||
padding-top: 2px;
|
||||
|
||||
&:before {
|
||||
text-align: center !important;
|
||||
width: 27px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
button[class*='icon-'] {
|
||||
color: $color-link;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.icon-envelope-alt, .icon-eye-open {
|
||||
color: $color-link;
|
||||
padding-left: 0px;
|
||||
|
||||
&:hover {
|
||||
background-color: $color-3;
|
||||
color: $color-1;
|
||||
}
|
||||
}
|
||||
.icon-trash:hover, .icon-void:hover {
|
||||
background-color: $color-error;
|
||||
color: $color-1;
|
||||
}
|
||||
.icon-cancel:hover {
|
||||
background-color: $color-notice;
|
||||
color: $color-1;
|
||||
}
|
||||
.icon-edit:hover, .icon-capture:hover, .icon-capture_and_complete_order:hover, .icon-ok:hover, .icon-plus:hover, .icon-road:hover {
|
||||
background-color: $color-success;
|
||||
color: $color-1;
|
||||
}
|
||||
.icon-copy:hover {
|
||||
background-color: $color-notice;
|
||||
color: $color-1;
|
||||
}
|
||||
}
|
||||
|
||||
input[type="number"],
|
||||
input[type="text"] {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&.no-border {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.handle {
|
||||
@extend .icon-reorder;
|
||||
font-family: FontAwesome;
|
||||
text-decoration: inherit;
|
||||
display: inline-block;
|
||||
speak: none;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&.no-borders {
|
||||
td, th {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
thead {
|
||||
th {
|
||||
padding: 10px;
|
||||
border-top: 1px solid $color-border;
|
||||
border-bottom: none;
|
||||
background-color: $color-tbl-thead;
|
||||
text-transform: uppercase;
|
||||
font-size: 85%;
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
}
|
||||
|
||||
tbody {
|
||||
tr {
|
||||
&:first-child th,
|
||||
&:first-child td {
|
||||
border-top: 1px solid $color-border;
|
||||
}
|
||||
&.even td {
|
||||
background-color: $color-tbl-even;
|
||||
|
||||
img {
|
||||
border: 1px solid very-light($color-3, 6);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover td {
|
||||
background-color: very-light($color-3, 5);
|
||||
|
||||
img {
|
||||
border: 1px solid $color-border;
|
||||
}
|
||||
}
|
||||
|
||||
&.deleted td {
|
||||
background-color: very-light($color-error, 6);
|
||||
border-color: very-light($color-error, 15);
|
||||
}
|
||||
|
||||
&.ui-sortable-placeholder td {
|
||||
border: 1px solid $color-2 !important;
|
||||
visibility: visible !important;
|
||||
|
||||
&.actions {
|
||||
background-color: transparent;
|
||||
border-right: none !important;
|
||||
border-top: none !important;
|
||||
border-bottom: none !important;
|
||||
border-left: 1px solid $color-2 !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.ui-sortable-helper {
|
||||
width: 100%;
|
||||
|
||||
td {
|
||||
background-color: lighten($color-3, 33);
|
||||
border-bottom: 1px solid $color-border;
|
||||
|
||||
&.actions {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.no-border-top tr:first-child td {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
&.grand-total {
|
||||
td {
|
||||
border-color: $color-2 !important;
|
||||
text-transform: uppercase;
|
||||
font-size: 110%;
|
||||
font-weight: 600;
|
||||
background-color: lighten($color-2, 50);
|
||||
}
|
||||
.total {
|
||||
background-color: $color-2;
|
||||
color: $color-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
// Base
|
||||
//--------------------------------------------------------------
|
||||
body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, form, p, blockquote, th, td { margin: 0; padding: 0; font-size: $body-font-size; }
|
||||
|
||||
body {
|
||||
font-family: $base-font-family;
|
||||
font-size: $body-font-size;
|
||||
font-weight: 400;
|
||||
color: $color-body-text;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
hr {
|
||||
border-top: 1px solid $color-border;
|
||||
border-bottom: 1px solid white;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
strong, b {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
// links
|
||||
//--------------------------------------------------------------
|
||||
a {
|
||||
color: $color-link;
|
||||
text-decoration: none;
|
||||
line-height: inherit;
|
||||
|
||||
&, &:hover, &:active, &:visited, &:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&:visited {
|
||||
color: $color-link-visited;
|
||||
}
|
||||
&:focus {
|
||||
color: $color-link-focus;
|
||||
}
|
||||
&:active {
|
||||
color: $color-link-active;
|
||||
}
|
||||
&:hover {
|
||||
color: $color-link-hover;
|
||||
}
|
||||
}
|
||||
|
||||
// Headings
|
||||
//--------------------------------------------------------------
|
||||
|
||||
h1,h2,h3,h4,h5,h6 {
|
||||
font-weight: 600;
|
||||
color: $color-headers;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
h1 { font-size: $h1-size; line-height: $h1-size + 6 }
|
||||
h2 { font-size: $h2-size; line-height: $h1-size + 4 }
|
||||
h3 { font-size: $h3-size; line-height: $h1-size + 2 }
|
||||
h4 { font-size: $h4-size; line-height: $h1-size }
|
||||
h5 { font-size: $h5-size; line-height: $h1-size }
|
||||
h6 { font-size: $h6-size; line-height: $h1-size }
|
||||
|
||||
|
||||
// Lists
|
||||
//--------------------------------------------------------------
|
||||
ul {
|
||||
&.inline-menu {
|
||||
li {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
&.fields {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
dl {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
margin: 5px 0;
|
||||
color: lighten($color-body-text, 15);
|
||||
|
||||
dt, dd {
|
||||
float: left;
|
||||
line-height: 16px;
|
||||
padding: 5px;
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
dt {
|
||||
width: 40%;
|
||||
font-weight: 600;
|
||||
padding-left: 0;
|
||||
text-transform: uppercase;
|
||||
font-size: 85%;
|
||||
}
|
||||
|
||||
dd {
|
||||
width: 60%;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
dd:after {
|
||||
content: '';
|
||||
clear: both;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Helpers
|
||||
.align-center { text-align: center }
|
||||
.align-right { text-align: right }
|
||||
.align-left { text-align: left }
|
||||
.align-justify { text-align: justify }
|
||||
|
||||
.uppercase { text-transform: uppercase }
|
||||
|
||||
.green { color: $color-2 }
|
||||
.blue { color: $color-3 }
|
||||
.red { color: $color-5 }
|
||||
.yellow { color: $color-6 }
|
||||
|
||||
.no-objects-found {
|
||||
text-align: center;
|
||||
font-size: 120%;
|
||||
text-transform: uppercase;
|
||||
padding: 40px 0px;
|
||||
color: lighten($color-body-text, 15);
|
||||
}
|
||||
|
||||
.text-normal {
|
||||
font-size: 1rem;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.text-big {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.text-red {
|
||||
color: $color-warning;
|
||||
}
|
||||
|
||||
input.text-big {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.pad-top {
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
.white-space-nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#banner-container {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: $tos-banner-z-index;
|
||||
|
||||
.terms-of-service-banner {
|
||||
padding: 18px;
|
||||
text-align: center;
|
||||
font-size: 120%;
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
margin-top: 0;
|
||||
background-color: rgba($color-notice, 0.8);
|
||||
display: flex;
|
||||
|
||||
.column-left {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.column-right {
|
||||
width: 30%;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
@import "../css/admin/all.scss";
|
||||
@import "../../../node_modules/trix/dist/trix.css";
|
||||
@@ -55,12 +55,30 @@ Openfoodnetwork::Application.configure do
|
||||
# config.active_support.deprecation = :stderr
|
||||
|
||||
# Fail tests on deprecated code unless it's a known case to solve.
|
||||
ActiveSupport::Deprecation.behavior = ->(message, callstack, deprecation_horizon, gem_name) do
|
||||
Rails.application.deprecators.behavior = ->(message, callstack, deprecator) do
|
||||
allowed_warnings = [
|
||||
# List strings here to allow matching deprecations.
|
||||
#
|
||||
# https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#new-activesupport-cache-serialization-format
|
||||
"config.active_support.cache_format_version",
|
||||
|
||||
# `Rails.application.secrets` is deprecated in favor of `Rails.application.credentials` and will be removed in Rails 7.2
|
||||
"Rails.application.secrets",
|
||||
|
||||
"Passing the class as positional argument",
|
||||
|
||||
# Spree::Order model aliases `bill_address`, but `bill_address` is not an attribute. Starting in Rails 7.2, alias_attribute with non-attribute targets will raise. Use `alias_method :billing_address, :bill_address` or define the method manually. (called from initialize at app/models/spree/order.rb:188)
|
||||
"alias_attribute with non-attribute targets will raise",
|
||||
|
||||
# Spree::CreditCard model aliases `cc_type` and has a method called `cc_type=` defined. Starting in Rails 7.2 `brand=` will not be calling `cc_type=` anymore. You may want to additionally define `brand=` to preserve the current behavior.
|
||||
"model aliases",
|
||||
|
||||
# Setting action_dispatch.show_exceptions to true is deprecated. Set to :all instead.
|
||||
# spec/requests/errors_spec.rb
|
||||
"action_dispatch.show_exceptions",
|
||||
]
|
||||
unless allowed_warnings.any? { |pattern| message.match(pattern) }
|
||||
ActiveSupport::Deprecation::DEFAULT_BEHAVIORS[:raise].call(message, callstack, deprecation_horizon, gem_name)
|
||||
ActiveSupport::Deprecation::DEFAULT_BEHAVIORS[:raise].call(message, callstack, deprecator)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -25,6 +25,12 @@ end
|
||||
Flipper.register(:new_2024_07_03) do |actor|
|
||||
actor.respond_to?(:created_at?) && actor.created_at >= "2024-07-03".to_time
|
||||
end
|
||||
Flipper.register(:enterprise_created_before_2025_08_11) do |actor|
|
||||
# This group applies to enterprises only, so we return false if the actor is not an Enterprise
|
||||
next false unless actor.actor.instance_of? Enterprise
|
||||
|
||||
actor.respond_to?(:created_at?) && actor.created_at < "2025-08-11".to_time
|
||||
end
|
||||
|
||||
Flipper::UI.configure do |config|
|
||||
config.descriptions_source = ->(_keys) do
|
||||
|
||||
@@ -110,6 +110,8 @@ ca:
|
||||
message_html: "<p>El canvi que volies va ser rebutjat. Potser heu intentat canviar alguna cosa a la qual no teniu accés.<br><h3> <a href='/' >Tornar a l'inici</a></h3></p>"
|
||||
general_error:
|
||||
message: "Ens sap greu, però alguna cosa ha anat malament.\n\n Pot ser que sigui un problema temporal, així que si us plau, torna-ho a provar o torna a carregar la pàgina.\n Enregistrem tots els errors i és possible que estiguem treballant en una solució.\n Si el problema persisteix o és urgent, poseu-vos en contacte amb nosaltres."
|
||||
unauthorized:
|
||||
message: "No rens permisos per a realitzar aquesta acció"
|
||||
stripe:
|
||||
error_code:
|
||||
incorrect_number: "El número de la targeta és incorrecte."
|
||||
@@ -275,6 +277,7 @@ ca:
|
||||
Ho analitzarem, però si el problema persisteix, si us plau, aviseu-nos.
|
||||
backorder_mailer:
|
||||
backorder_failed:
|
||||
stock: "Estoc"
|
||||
product: "Producte"
|
||||
enterprise_mailer:
|
||||
confirmation_instructions:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user