mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-19 19:46:51 +00:00
Compare commits
223 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e7c50e22b | ||
|
|
9b4538790e | ||
|
|
075b8d2585 | ||
|
|
b54f4ef686 | ||
|
|
4a8e3a751d | ||
|
|
6472070517 | ||
|
|
26402397ea | ||
|
|
b19456535d | ||
|
|
a177f4c066 | ||
|
|
19c4596b9e | ||
|
|
0c769706aa | ||
|
|
65843fbd68 | ||
|
|
d2e6b7d164 | ||
|
|
fd1391cda9 | ||
|
|
54c58c6ba6 | ||
|
|
e04a23cb3c | ||
|
|
4364b1283b | ||
|
|
da5fa8f608 | ||
|
|
3f8ca55975 | ||
|
|
287f0572c2 | ||
|
|
ec5077c75b | ||
|
|
657fd72f69 | ||
|
|
eb663af292 | ||
|
|
5c04d00ff8 | ||
|
|
fd446970ca | ||
|
|
be004383a4 | ||
|
|
1e77b96c2c | ||
|
|
b2db63178f | ||
|
|
798f1dfdfa | ||
|
|
ee70645d04 | ||
|
|
c4b89e466b | ||
|
|
57aeee94f9 | ||
|
|
3a9be42389 | ||
|
|
b7930e7d38 | ||
|
|
7c69cc5aa9 | ||
|
|
2baa55262b | ||
|
|
2835265a1e | ||
|
|
bd20a8c16f | ||
|
|
61175c036a | ||
|
|
6b3a0fa14a | ||
|
|
e403a2c174 | ||
|
|
5aca76e520 | ||
|
|
73a2b90e1b | ||
|
|
c7d4c4c195 | ||
|
|
bba1d6c725 | ||
|
|
52cb6d4eec | ||
|
|
fc6bd53720 | ||
|
|
650fd69f60 | ||
|
|
22a086ebc1 | ||
|
|
446fa2ddab | ||
|
|
59a565c446 | ||
|
|
dc6ac99a3f | ||
|
|
5c8c4c36f7 | ||
|
|
be25ea0b9e | ||
|
|
9cba9395e3 | ||
|
|
cdd39f526d | ||
|
|
31f7cadd92 | ||
|
|
972e0b5d0b | ||
|
|
927c1c81e5 | ||
|
|
fd87013a63 | ||
|
|
274e0d0335 | ||
|
|
c5f3d3fa71 | ||
|
|
26684f7db5 | ||
|
|
2ccb7de004 | ||
|
|
7c321922ad | ||
|
|
d7e3e81c8c | ||
|
|
d7454ecb9f | ||
|
|
4c172b5ace | ||
|
|
6529a8d98f | ||
|
|
ccfc632149 | ||
|
|
32ec39ad8c | ||
|
|
449d500371 | ||
|
|
cbb7e52795 | ||
|
|
1eb1beda3b | ||
|
|
da4069679c | ||
|
|
b858371735 | ||
|
|
992b497b75 | ||
|
|
53fa2ef8d5 | ||
|
|
79f602b4ea | ||
|
|
ab39341192 | ||
|
|
edc0c189df | ||
|
|
7e844ee289 | ||
|
|
bcc9d447e1 | ||
|
|
9997fe26fc | ||
|
|
519c15a9d5 | ||
|
|
64ca0a4eea | ||
|
|
2fde3abe37 | ||
|
|
c3805b8187 | ||
|
|
70b1888d45 | ||
|
|
f03df26e4e | ||
|
|
662ca16aa3 | ||
|
|
07f9379956 | ||
|
|
f122f4bf50 | ||
|
|
4a250f41f3 | ||
|
|
388923e963 | ||
|
|
235f4bb767 | ||
|
|
3a3fc066dc | ||
|
|
f3ff70a9f2 | ||
|
|
5ae6223a8c | ||
|
|
a465093d12 | ||
|
|
95c9f9afbb | ||
|
|
2842f2bb9e | ||
|
|
dc8ccba972 | ||
|
|
a0d7f10256 | ||
|
|
d5ef68323e | ||
|
|
6c1c103272 | ||
|
|
985cf990d6 | ||
|
|
22eee4493f | ||
|
|
74b618230f | ||
|
|
5601a6d3b6 | ||
|
|
7b7718977f | ||
|
|
c54942d1ce | ||
|
|
fdc78b717e | ||
|
|
95821098d8 | ||
|
|
27643945ed | ||
|
|
b0048cb453 | ||
|
|
1e1ec95a5a | ||
|
|
2d86e8857a | ||
|
|
f1bb4fdf38 | ||
|
|
a6856f3d21 | ||
|
|
ca1a850d4a | ||
|
|
921e1f8083 | ||
|
|
928b4144d5 | ||
|
|
93e736fdf6 | ||
|
|
988dcc6081 | ||
|
|
d43f0331ac | ||
|
|
dcbe9dd1cb | ||
|
|
c96bba8094 | ||
|
|
45a49d01ec | ||
|
|
3b6d0a8760 | ||
|
|
5f4aed92d8 | ||
|
|
a118c786ef | ||
|
|
1572a81274 | ||
|
|
6f8dc4dd79 | ||
|
|
6879643044 | ||
|
|
2a0cd5e275 | ||
|
|
af7c11bb3e | ||
|
|
046d7d5f44 | ||
|
|
81e1bb19a3 | ||
|
|
d30d3d256d | ||
|
|
850c845992 | ||
|
|
f1b81613d6 | ||
|
|
e3914ed306 | ||
|
|
ef092dd53a | ||
|
|
5e0287d93f | ||
|
|
58fb2ebe29 | ||
|
|
0d37614e90 | ||
|
|
cb4b54c927 | ||
|
|
a9a7ad5cb3 | ||
|
|
46562aace7 | ||
|
|
a57d1863c0 | ||
|
|
fd74473bdd | ||
|
|
78c29f2c6a | ||
|
|
7a62a95e0b | ||
|
|
b8e4dcac7c | ||
|
|
944d552f6b | ||
|
|
c3e4c53a01 | ||
|
|
ae59621341 | ||
|
|
d61affd82b | ||
|
|
c0364a845d | ||
|
|
47e100607c | ||
|
|
7f17bfaa9a | ||
|
|
e9f92d39aa | ||
|
|
23462e9965 | ||
|
|
0d0c568b10 | ||
|
|
155b8ed725 | ||
|
|
11ea6b39cf | ||
|
|
18e9aba6b8 | ||
|
|
561458ce43 | ||
|
|
6f3d27b99b | ||
|
|
8e5495c34d | ||
|
|
59b727aa95 | ||
|
|
3b179e75a4 | ||
|
|
2ff50587d8 | ||
|
|
2296a51dd2 | ||
|
|
33896a73f3 | ||
|
|
d97f49d1d4 | ||
|
|
c000010d0b | ||
|
|
26baad53e4 | ||
|
|
86c437ee24 | ||
|
|
19bd067379 | ||
|
|
20596b9441 | ||
|
|
d8e22a5ee7 | ||
|
|
896743ee34 | ||
|
|
f935a27253 | ||
|
|
54fd768aa4 | ||
|
|
89acd3a589 | ||
|
|
819cf5cc49 | ||
|
|
10b0f9b650 | ||
|
|
67cca34daa | ||
|
|
19f3fd872f | ||
|
|
3175f0f68c | ||
|
|
5f7f7c78b0 | ||
|
|
aa26e15e6b | ||
|
|
64d467ce39 | ||
|
|
727e6d4966 | ||
|
|
66134c24b7 | ||
|
|
19d5723dd6 | ||
|
|
03c38aee3c | ||
|
|
ada76a9bf7 | ||
|
|
bf073599d7 | ||
|
|
faf106b282 | ||
|
|
d79b4bdcf9 | ||
|
|
d90d352a86 | ||
|
|
1ca305ab7c | ||
|
|
ea07795304 | ||
|
|
741dc0e29c | ||
|
|
a0056553b0 | ||
|
|
87ae8a40d1 | ||
|
|
ac494f97ec | ||
|
|
ea45462e50 | ||
|
|
e971f46611 | ||
|
|
5fd78a8db5 | ||
|
|
311675f2cf | ||
|
|
97c3aaebb2 | ||
|
|
4716ed19dc | ||
|
|
cd743e5c2c | ||
|
|
bfd396e644 | ||
|
|
84aedaa1a1 | ||
|
|
86c25e1d48 | ||
|
|
368cd76611 | ||
|
|
ccddb7ad65 | ||
|
|
764c8d7d27 |
3
.github/ISSUE_TEMPLATE/release.md
vendored
3
.github/ISSUE_TEMPLATE/release.md
vendored
@@ -23,8 +23,7 @@ assignees: ''
|
||||
|
||||
## Finish on Tuesday
|
||||
|
||||
- [ ] Publish and notify [#global-community]:
|
||||
> The next release is ready: https://github.com/openfoodfoundation/openfoodnetwork/releases/latest
|
||||
- [ ] Publish and notify [#global-community] (this is automatically posted with a plugin)
|
||||
- [ ] Deploy the new release to all managed instances.
|
||||
<details><summary>Command line instructions</summary>
|
||||
<pre>
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -50,7 +50,6 @@ vendor/bundle/
|
||||
coverage
|
||||
/reports/
|
||||
!/reports/README.md
|
||||
/spec/components/stories/**/*.stories.json
|
||||
|
||||
/public/packs
|
||||
/public/packs-test
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
babel.config.js
|
||||
postcss.config.js
|
||||
|
||||
.storybook/
|
||||
/app/assets/
|
||||
/config/
|
||||
/coverage/
|
||||
|
||||
@@ -684,17 +684,6 @@ Rails/ApplicationController:
|
||||
Exclude:
|
||||
- 'engines/dfc_provider/app/controllers/dfc_provider/base_controller.rb'
|
||||
|
||||
# Offense count: 6
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Rails/ApplicationJob:
|
||||
Exclude:
|
||||
- 'app/jobs/bulk_invoice_job.rb'
|
||||
- 'app/jobs/heartbeat_job.rb'
|
||||
- 'app/jobs/order_cycle_closing_job.rb'
|
||||
- 'app/jobs/order_cycle_notification_job.rb'
|
||||
- 'app/jobs/subscription_confirm_job.rb'
|
||||
- 'app/jobs/subscription_placement_job.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Rails/ApplicationMailer:
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
module.exports = {
|
||||
stories: ['../spec/components/stories/**/*.stories.json'],
|
||||
addons: [
|
||||
'@storybook/addon-docs',
|
||||
'@storybook/addon-controls',
|
||||
],
|
||||
};
|
||||
@@ -1,2 +0,0 @@
|
||||
<link href='https://fonts.googleapis.com/css?family=Roboto:400,300italic,400italic,300,700,700italic|Oswald:300,400,700' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" media="screen" href="http://localhost:3000/assets/darkswarm/all.css" />
|
||||
@@ -1,5 +0,0 @@
|
||||
export const parameters = {
|
||||
server: {
|
||||
url: `http://localhost:3000/rails/stories`,
|
||||
},
|
||||
};
|
||||
3
Gemfile
3
Gemfile
@@ -118,7 +118,7 @@ gem 'test-unit', '~> 3.5'
|
||||
|
||||
gem 'coffee-rails', '~> 5.0.0'
|
||||
|
||||
gem 'mini_racer', '0.4.0'
|
||||
gem 'mini_racer'
|
||||
|
||||
gem 'angular_rails_csrf'
|
||||
|
||||
@@ -185,7 +185,6 @@ group :development do
|
||||
gem 'spring-commands-rspec'
|
||||
gem 'web-console'
|
||||
|
||||
gem "view_component_storybook"
|
||||
|
||||
gem 'rack-mini-profiler', '< 3.0.0'
|
||||
end
|
||||
|
||||
67
Gemfile.lock
67
Gemfile.lock
@@ -179,10 +179,10 @@ GEM
|
||||
bindex (0.8.1)
|
||||
bootsnap (1.15.0)
|
||||
msgpack (~> 1.2)
|
||||
bugsnag (6.25.0)
|
||||
bugsnag (6.25.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
builder (3.2.4)
|
||||
bullet (7.0.4)
|
||||
bullet (7.0.7)
|
||||
activesupport (>= 3.0.0)
|
||||
uniform_notifier (~> 1.11)
|
||||
cable_ready (5.0.0.pre9)
|
||||
@@ -241,7 +241,7 @@ GEM
|
||||
debase-ruby_core_source (= 0.10.12)
|
||||
msgpack
|
||||
debase-ruby_core_source (0.10.12)
|
||||
debug (1.7.0)
|
||||
debug (1.7.1)
|
||||
irb (>= 1.5.0)
|
||||
reline (>= 0.3.1)
|
||||
debugger-linecache (1.2.0)
|
||||
@@ -349,9 +349,9 @@ GEM
|
||||
ruby-vips (>= 2.0.17, < 3)
|
||||
immigrant (0.3.6)
|
||||
activerecord (>= 3.0)
|
||||
io-console (0.5.11)
|
||||
io-console (0.6.0)
|
||||
ipaddress (0.8.3)
|
||||
irb (1.5.1)
|
||||
irb (1.6.2)
|
||||
reline (>= 0.3.0)
|
||||
jmespath (1.6.2)
|
||||
jquery-rails (4.4.0)
|
||||
@@ -374,15 +374,15 @@ GEM
|
||||
rspec (>= 2.0, < 4.0)
|
||||
jsonapi-serializer (2.2.0)
|
||||
activesupport (>= 4.2)
|
||||
jwt (2.5.0)
|
||||
knapsack_pro (3.6.0)
|
||||
jwt (2.6.0)
|
||||
knapsack_pro (3.7.0)
|
||||
rake
|
||||
launchy (2.5.0)
|
||||
addressable (~> 2.7)
|
||||
letter_opener (1.8.1)
|
||||
launchy (>= 2.2, < 3)
|
||||
libv8-node (15.14.0.1)
|
||||
listen (3.7.1)
|
||||
libv8-node (16.10.0.0)
|
||||
listen (3.8.0)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
loofah (2.19.1)
|
||||
@@ -401,10 +401,10 @@ GEM
|
||||
rake
|
||||
mini_magick (4.11.0)
|
||||
mini_mime (1.1.2)
|
||||
mini_portile2 (2.8.0)
|
||||
mini_racer (0.4.0)
|
||||
libv8-node (~> 15.14.0.0)
|
||||
minitest (5.16.3)
|
||||
mini_portile2 (2.8.1)
|
||||
mini_racer (0.6.3)
|
||||
libv8-node (~> 16.10.0.0)
|
||||
minitest (5.17.0)
|
||||
monetize (1.12.0)
|
||||
money (~> 6.12)
|
||||
money (6.16.0)
|
||||
@@ -453,7 +453,7 @@ GEM
|
||||
parallel (1.22.1)
|
||||
paranoia (2.6.1)
|
||||
activerecord (>= 5.1, < 7.1)
|
||||
parser (3.1.3.0)
|
||||
parser (3.2.0.0)
|
||||
ast (~> 2.4.1)
|
||||
paypal-sdk-core (0.3.4)
|
||||
multi_json (~> 1.0)
|
||||
@@ -472,7 +472,7 @@ GEM
|
||||
coderay (~> 1.1)
|
||||
method_source (~> 1.0)
|
||||
public_suffix (5.0.0)
|
||||
puma (5.6.5)
|
||||
puma (6.0.2)
|
||||
nio4r (~> 2.0)
|
||||
raabro (1.4.0)
|
||||
racc (1.6.1)
|
||||
@@ -540,13 +540,13 @@ GEM
|
||||
activerecord (>= 5.2.4)
|
||||
activesupport (>= 5.2.4)
|
||||
i18n
|
||||
rb-fsevent (0.11.0)
|
||||
rb-fsevent (0.11.2)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
redcarpet (3.5.1)
|
||||
redis (4.8.0)
|
||||
regexp_parser (2.6.1)
|
||||
reline (0.3.1)
|
||||
reline (0.3.2)
|
||||
io-console (~> 0.5)
|
||||
request_store (1.5.0)
|
||||
rack (>= 1.4)
|
||||
@@ -599,19 +599,19 @@ GEM
|
||||
rswag-ui (2.8.0)
|
||||
actionpack (>= 3.1, < 7.1)
|
||||
railties (>= 3.1, < 7.1)
|
||||
rubocop (1.40.0)
|
||||
rubocop (1.43.0)
|
||||
json (~> 2.3)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 3.1.2.1)
|
||||
parser (>= 3.2.0.0)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 1.8, < 3.0)
|
||||
rexml (>= 3.2.5, < 4.0)
|
||||
rubocop-ast (>= 1.23.0, < 2.0)
|
||||
rubocop-ast (>= 1.24.1, < 2.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 1.4.0, < 3.0)
|
||||
rubocop-ast (1.24.0)
|
||||
unicode-display_width (>= 2.4.0, < 3.0)
|
||||
rubocop-ast (1.24.1)
|
||||
parser (>= 3.1.1.0)
|
||||
rubocop-rails (2.17.3)
|
||||
rubocop-rails (2.17.4)
|
||||
activesupport (>= 4.2.0)
|
||||
rack (>= 1.1)
|
||||
rubocop (>= 1.33.0, < 2.0)
|
||||
@@ -634,7 +634,7 @@ GEM
|
||||
tilt (>= 1.1, < 3)
|
||||
sd_notify (0.1.1)
|
||||
semantic_range (3.0.0)
|
||||
shoulda-matchers (5.2.0)
|
||||
shoulda-matchers (5.3.0)
|
||||
activesupport (>= 5.2.0)
|
||||
sidekiq (6.5.8)
|
||||
connection_pool (>= 2.2.5, < 3)
|
||||
@@ -645,16 +645,16 @@ GEM
|
||||
rufus-scheduler (~> 3.2)
|
||||
sidekiq (>= 4, < 7)
|
||||
tilt (>= 1.4.0)
|
||||
simplecov (0.21.2)
|
||||
simplecov (0.22.0)
|
||||
docile (~> 1.1)
|
||||
simplecov-html (~> 0.11)
|
||||
simplecov_json_formatter (~> 0.1)
|
||||
simplecov-html (0.12.3)
|
||||
simplecov_json_formatter (0.1.3)
|
||||
simplecov_json_formatter (0.1.4)
|
||||
spreadsheet_architect (5.0.0)
|
||||
caxlsx (>= 3.3.0, < 4)
|
||||
rodf (>= 1.0.0, < 2)
|
||||
spring (4.1.0)
|
||||
spring (4.1.1)
|
||||
spring-commands-rspec (1.0.4)
|
||||
spring (>= 0.9.1)
|
||||
sprockets (3.7.2)
|
||||
@@ -698,7 +698,7 @@ GEM
|
||||
ttfunk (1.7.0)
|
||||
tzinfo (2.0.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
unicode-display_width (2.3.0)
|
||||
unicode-display_width (2.4.2)
|
||||
uniform_notifier (1.16.0)
|
||||
valid_email2 (4.0.4)
|
||||
activemodel (>= 3.2)
|
||||
@@ -710,16 +710,14 @@ GEM
|
||||
activemodel (>= 3.0.0)
|
||||
public_suffix
|
||||
vcr (6.1.0)
|
||||
view_component (2.79.0)
|
||||
activesupport (>= 5.0.0, < 8.0)
|
||||
view_component (2.82.0)
|
||||
activesupport (>= 5.2.0, < 8.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
method_source (~> 1.0)
|
||||
view_component_reflex (3.1.14.pre9)
|
||||
rails (>= 5.2, < 8.0)
|
||||
stimulus_reflex (>= 3.5.0.pre2)
|
||||
view_component (>= 2.28.0)
|
||||
view_component_storybook (0.11.1)
|
||||
view_component (>= 2.36)
|
||||
warden (1.2.9)
|
||||
rack (>= 2.0.9)
|
||||
web-console (4.2.0)
|
||||
@@ -827,7 +825,7 @@ DEPENDENCIES
|
||||
mime-types
|
||||
mimemagic (> 0.3.5)
|
||||
mini_portile2 (~> 2.8)
|
||||
mini_racer (= 0.4.0)
|
||||
mini_racer
|
||||
monetize (~> 1.11)
|
||||
oauth2 (~> 1.4.7)
|
||||
ofn-qz!
|
||||
@@ -884,7 +882,6 @@ DEPENDENCIES
|
||||
vcr
|
||||
view_component
|
||||
view_component_reflex (= 3.1.14.pre9)
|
||||
view_component_storybook
|
||||
web!
|
||||
web-console
|
||||
webmock
|
||||
@@ -897,4 +894,4 @@ RUBY VERSION
|
||||
ruby 3.0.3p157
|
||||
|
||||
BUNDLED WITH
|
||||
2.1.4
|
||||
2.4.3
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
angular.module("admin.indexUtils").component 'showMore',
|
||||
templateUrl: 'admin/show_more.html'
|
||||
bindings:
|
||||
data: "="
|
||||
limit: "="
|
||||
increment: "="
|
||||
|
||||
# For now, this component is not being used.
|
||||
# Something about binding "data" to a variable on the parent scope that is continually refreshed by
|
||||
# being assigned within an ng-repeat means that we get $digest iteration errors. Seems to be solved
|
||||
# by using the new "as" syntax for ng-repeat to assign and alias the outcome of the filters, but this
|
||||
# has the limitation of not being able to be limited AFTER the assignment has been made, which we need
|
||||
@@ -3,10 +3,6 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
$scope.RequestMonitor = RequestMonitor
|
||||
$scope.line_items = LineItems.all
|
||||
$scope.confirmDelete = true
|
||||
$scope.startDate = moment().startOf('day').subtract(7, 'days').format('YYYY-MM-DD')
|
||||
$scope.endDate = moment().startOf('day').format('YYYY-MM-DD')
|
||||
$scope.previousDates = { startDate: $scope.startDate, endDate: $scope.endDate }
|
||||
$scope.datesChangedOnCancelEvent = false
|
||||
$scope.bulkActions = [ { name: t("admin.orders.bulk_management.actions_delete"), callback: 'deleteLineItems' } ]
|
||||
$scope.selectedUnitsProduct = {}
|
||||
$scope.selectedUnitsVariant = {}
|
||||
@@ -17,42 +13,29 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
$scope.confirmRefresh = ->
|
||||
LineItems.allSaved() || confirm(t("unsaved_changes_warning"))
|
||||
|
||||
$scope.initStartAndEnDate = ->
|
||||
$scope.startDate = moment().startOf('day').subtract(7, 'days').format('YYYY-MM-DD')
|
||||
$scope.endDate = moment().startOf('day').format('YYYY-MM-DD')
|
||||
|
||||
$scope.resetFilters = ->
|
||||
$scope.distributorFilter = ''
|
||||
$scope.supplierFilter = ''
|
||||
$scope.orderCycleFilter = ''
|
||||
$scope.quickSearch = ''
|
||||
$scope.initStartAndEnDate()
|
||||
event = new CustomEvent('flatpickr:change', {
|
||||
detail: {
|
||||
startDate: $scope.startDate,
|
||||
endDate: $scope.endDate
|
||||
}
|
||||
})
|
||||
window.dispatchEvent(event)
|
||||
|
||||
$scope.resetSelectFilters = ->
|
||||
$scope.resetFilters()
|
||||
$scope.refreshData()
|
||||
|
||||
$scope.$watchCollection "[startDate, endDate]", (newValues, oldValues) ->
|
||||
if newValues != oldValues && !$scope.datesChangedOnCancelEvent
|
||||
state = $scope.refreshData()
|
||||
if (state == "cancel")
|
||||
$scope.datesChangedOnCancelEvent = true
|
||||
$scope.cancelDateChange()
|
||||
|
||||
$scope.cancelDateChange = ->
|
||||
# Reset the date filters to the previous values
|
||||
$scope.startDate = $scope.previousDates.startDate
|
||||
$scope.endDate = $scope.previousDates.endDate
|
||||
# throw a flatpickr:change event to change the date back in the datepicker
|
||||
event = new CustomEvent('flatpickr:change', {
|
||||
detail: {
|
||||
startDate: $scope.previousDates.startDate,
|
||||
endDate: $scope.previousDates.endDate
|
||||
}
|
||||
})
|
||||
window.dispatchEvent(event)
|
||||
$timeout ->
|
||||
$scope.datesChangedOnCancelEvent = false
|
||||
|
||||
$scope.refreshData = ->
|
||||
unless !$scope.orderCycleFilter? || $scope.orderCycleFilter == ''
|
||||
$scope.setOrderCycleDateRange()
|
||||
|
||||
$scope.formattedStartDate = moment($scope.startDate).format()
|
||||
$scope.formattedEndDate = moment($scope.endDate).add(1,'day').format()
|
||||
|
||||
@@ -67,11 +50,6 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
$scope.loadAssociatedData()
|
||||
|
||||
$scope.dereferenceLoadedData()
|
||||
|
||||
$timeout ->
|
||||
# update the previous dates with the current ones since loading was successful
|
||||
$scope.previousDates.startDate = $scope.startDate
|
||||
$scope.previousDates.endDate = $scope.endDate
|
||||
|
||||
$scope.setOrderCycleDateRange = ->
|
||||
start_date = OrderCycles.byID[$scope.orderCycleFilter].orders_open_at
|
||||
@@ -79,6 +57,14 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
format = "YYYY-MM-DD HH:mm:ss Z"
|
||||
$scope.startDate = moment(start_date, format).format('YYYY-MM-DD')
|
||||
$scope.endDate = moment(end_date, format).startOf('day').format('YYYY-MM-DD')
|
||||
# throw a flatpickr:change event to change the date back in the datepicker
|
||||
event = new CustomEvent('flatpickr:change', {
|
||||
detail: {
|
||||
startDate: $scope.startDate,
|
||||
endDate: $scope.endDate
|
||||
}
|
||||
})
|
||||
window.dispatchEvent(event)
|
||||
|
||||
$scope.loadOrders = ->
|
||||
RequestMonitor.load $scope.orders = Orders.index(
|
||||
@@ -277,5 +263,4 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
lineItem.final_weight_volume = LineItems.pristineByID[lineItem.id].final_weight_volume * lineItem.quantity / LineItems.pristineByID[lineItem.id].quantity
|
||||
$scope.weightAdjustedPrice(lineItem)
|
||||
|
||||
$scope.resetFilters()
|
||||
$scope.refreshData()
|
||||
$scope.resetSelectFilters()
|
||||
|
||||
@@ -21,8 +21,14 @@ angular.module("admin.products")
|
||||
else
|
||||
$scope.product.variant_unit = $scope.product.variant_unit_with_scale
|
||||
$scope.product.variant_unit_scale = null
|
||||
else if $scope.product.variant_unit && $scope.product.variant_unit_scale
|
||||
$scope.product.variant_unit_with_scale = VariantUnitManager.getUnitWithScale($scope.product.variant_unit, parseFloat($scope.product.variant_unit_scale))
|
||||
else if $scope.product.variant_unit
|
||||
# Preserves variant_unit_with_scale when form validation fails and reload triggers
|
||||
if $scope.product.variant_unit_scale
|
||||
$scope.product.variant_unit_with_scale = VariantUnitManager.getUnitWithScale(
|
||||
$scope.product.variant_unit, parseFloat($scope.product.variant_unit_scale)
|
||||
)
|
||||
else
|
||||
$scope.product.variant_unit_with_scale = $scope.product.variant_unit
|
||||
else
|
||||
$scope.product.variant_unit = $scope.product.variant_unit_scale = null
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
angular.module('Darkswarm').directive "fillVertical", ($window)->
|
||||
# Makes something fill the window vertically. Used on the Google Map.
|
||||
restrict: 'A'
|
||||
link: (scope, element, attrs)->
|
||||
setSize = ->
|
||||
element.css "height", ($window.innerHeight - element.offset().top)
|
||||
setSize()
|
||||
angular.element($window).bind "resize", ->
|
||||
setSize()
|
||||
@@ -1,82 +0,0 @@
|
||||
angular.module('Darkswarm').directive 'singleLineSelectors', ($timeout, $filter) ->
|
||||
restrict: 'E'
|
||||
templateUrl: "single_line_selectors.html"
|
||||
scope:
|
||||
selectors: "="
|
||||
objects: "&"
|
||||
activeSelectors: "="
|
||||
selectorName: "@activeSelectors"
|
||||
link: (scope, element, attrs) ->
|
||||
scope.fitting = false
|
||||
|
||||
scope.refit = ->
|
||||
if scope.allSelectors?
|
||||
scope.fitting = true
|
||||
selector.fits = true for selector in scope.allSelectors
|
||||
$timeout(loadWidths, 0, true).then ->
|
||||
$timeout fit, 0, true
|
||||
|
||||
fit = ->
|
||||
used = $(element).find("li.more").outerWidth(true)
|
||||
used += selector.width for selector in scope.allSelectors when selector.fits
|
||||
available = $(element).parent(".filter-shopfront").innerWidth() - used
|
||||
if available > 0
|
||||
for selector in scope.allSelectors when !selector.fits
|
||||
available -= selector.width
|
||||
selector.fits = true if available > 0
|
||||
else
|
||||
if scope.allSelectors.length > 0
|
||||
for i in [scope.allSelectors.length-1..0]
|
||||
selector = scope.allSelectors[i]
|
||||
if !selector.fits
|
||||
continue
|
||||
else
|
||||
if available < 0
|
||||
selector.fits = false
|
||||
available += selector.width
|
||||
scope.fitting = false
|
||||
|
||||
loadWidths = ->
|
||||
$(element).find("li").not(".more").each (i) ->
|
||||
if i < scope.allSelectors.length
|
||||
scope.allSelectors[i].width = $(this).outerWidth(true)
|
||||
return null # So we don't exit the loop weirdly
|
||||
|
||||
scope.overFlowSelectors = ->
|
||||
return [] unless scope.allSelectors?
|
||||
$filter('filter')(scope.allSelectors, { fits: false })
|
||||
|
||||
scope.selectedOverFlowSelectors = ->
|
||||
$filter('filter')(scope.overFlowSelectors(), { active: true })
|
||||
|
||||
# had to duplicate this to make overflow selectors work
|
||||
scope.emit = ->
|
||||
scope.activeSelectors = scope.allSelectors.filter (selector)->
|
||||
selector.active
|
||||
.map (selector) ->
|
||||
selector.object.id
|
||||
|
||||
# From: http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing
|
||||
debouncer = (func, timeout) ->
|
||||
timeoutID = undefined
|
||||
timeout = timeout or 50
|
||||
->
|
||||
subject = this
|
||||
args = arguments
|
||||
clearTimeout timeoutID
|
||||
timeoutID = setTimeout(->
|
||||
func.apply subject, Array::slice.call(args)
|
||||
, timeout)
|
||||
|
||||
|
||||
# -- Event management
|
||||
scope.$watchCollection "allSelectors", ->
|
||||
scope.refit()
|
||||
|
||||
scope.$on "filtersToggled", ->
|
||||
scope.refit()
|
||||
|
||||
$(window).resize debouncer (e) ->
|
||||
scope.fitting = true
|
||||
if scope.allSelectors?
|
||||
$timeout fit, 0, true
|
||||
@@ -1,3 +0,0 @@
|
||||
%div{ ng: { show: "data.length > limit" } }
|
||||
%input{ type: 'button', value: t(:show_more), ng: { click: 'limit = limit + increment' } }
|
||||
%input{ type: 'button', value: t(:show_all_with_more, num: '{{ data.length - limit }}'), ng: { click: 'limit = data.length' } }
|
||||
@@ -1,14 +0,0 @@
|
||||
-# In order for the single-line-selector scope to have access to the available selectors,
|
||||
%filter-selector{"selector-set" => "selectors", objects: "objects()", "active-selectors" => "activeSelectors", "all-selectors" => "allSelectors" }
|
||||
|
||||
%ul{ ng: { if: "overFlowSelectors().length > 0 || fitting" } }
|
||||
%li.more
|
||||
%a.dropdown{ data: { dropdown: "{{ 'show-more-' + selectorName }}" }, ng: { class: "{active: selectedOverFlowSelectors().length > 0}" } }
|
||||
%span
|
||||
{{ 'js.more_items' | t:{ count: overFlowSelectors().length } }}
|
||||
%i.ofn-i_052-point-down
|
||||
.f-dropdown.text-right.content{ ng: { attr: { id: "{{ 'show-more-' + selectorName }}" } } }
|
||||
%ul
|
||||
%active-selector{ ng: { repeat: "selector in overFlowSelectors()", hide: "selector.fits" } }
|
||||
%render-svg{path: "{{selector.object.icon}}", ng: { if: "selector.object.icon"}}
|
||||
%span {{ selector.object.name }}
|
||||
15
app/components/confirm_modal_component.rb
Normal file
15
app/components/confirm_modal_component.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ConfirmModalComponent < ModalComponent
|
||||
def initialize(id:, confirm_actions: nil, controllers: nil)
|
||||
super(id: id, close_button: true)
|
||||
@confirm_actions = confirm_actions
|
||||
@controllers = controllers
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def close_button_class
|
||||
"secondary"
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
%div{ id: @id, "data-controller": "modal #{@controllers}", "data-action": "keyup@document->modal#closeIfEscapeKey" }
|
||||
.reveal-modal-bg.fade{ "data-modal-target": "background", "data-action": "click->modal#close" }
|
||||
.reveal-modal.fade.tiny.help-modal{ "data-modal-target": "modal" }
|
||||
= content
|
||||
|
||||
.modal-actions
|
||||
%input{ class: "button icon-plus #{close_button_class}", type: 'button', value: t('js.admin.modals.cancel'), "data-action": "click->modal#close" }
|
||||
%input{ class: "button icon-plus primary", type: 'button', value: t('js.admin.modals.confirm'), "data-action": @confirm_actions }
|
||||
@@ -0,0 +1,4 @@
|
||||
.modal-actions {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
@@ -1,26 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class HelpModalComponent < ViewComponent::Base
|
||||
class HelpModalComponent < ModalComponent
|
||||
def initialize(id:, close_button: true)
|
||||
@id = id
|
||||
@close_button = close_button
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def close_button_class
|
||||
if namespace == "admin"
|
||||
"red"
|
||||
else
|
||||
"primary"
|
||||
end
|
||||
end
|
||||
|
||||
def close_button?
|
||||
!!@close_button
|
||||
end
|
||||
|
||||
def namespace
|
||||
helpers.controller_path.split("/").first
|
||||
super(id: id, close_button: close_button)
|
||||
end
|
||||
end
|
||||
|
||||
26
app/components/modal_component.rb
Normal file
26
app/components/modal_component.rb
Normal file
@@ -0,0 +1,26 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ModalComponent < ViewComponent::Base
|
||||
def initialize(id:, close_button: true)
|
||||
@id = id
|
||||
@close_button = close_button
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def close_button_class
|
||||
if namespace == "admin"
|
||||
"red"
|
||||
else
|
||||
"primary"
|
||||
end
|
||||
end
|
||||
|
||||
def close_button?
|
||||
!!@close_button
|
||||
end
|
||||
|
||||
def namespace
|
||||
helpers.controller_path.split("/").first
|
||||
end
|
||||
end
|
||||
@@ -3,11 +3,16 @@
|
||||
require "open_food_network/feature_toggle"
|
||||
|
||||
class FeatureToggleConstraint
|
||||
def initialize(feature_name)
|
||||
def initialize(feature_name, negate: false)
|
||||
@feature = feature_name
|
||||
@negate = negate
|
||||
end
|
||||
|
||||
def matches?(request)
|
||||
enabled?(request) ^ @negate
|
||||
end
|
||||
|
||||
def enabled?(request)
|
||||
OpenFoodNetwork::FeatureToggle.enabled?(@feature, current_user(request))
|
||||
end
|
||||
|
||||
|
||||
@@ -19,22 +19,22 @@ module Admin
|
||||
end
|
||||
|
||||
def show
|
||||
@report = report_class.new(spree_current_user, params, request)
|
||||
@report = report_class.new(spree_current_user, params, render: render_data?)
|
||||
|
||||
if report_format.present?
|
||||
export_report
|
||||
else
|
||||
render_report
|
||||
show_report
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def export_report
|
||||
send_data @report.render_as(report_format, controller: self), filename: report_filename
|
||||
send_data render_report_as(report_format), filename: report_filename
|
||||
end
|
||||
|
||||
def render_report
|
||||
def show_report
|
||||
assign_view_data
|
||||
render "show"
|
||||
end
|
||||
@@ -43,13 +43,29 @@ module Admin
|
||||
@report_type = report_type
|
||||
@report_subtypes = report_subtypes
|
||||
@report_subtype = report_subtype
|
||||
@report_title = if report_subtype
|
||||
report_subtype_title
|
||||
else
|
||||
I18n.t(:name, scope: [:admin, :reports, @report_type])
|
||||
end
|
||||
@report_title = report_title
|
||||
@rendering_options = rendering_options
|
||||
@table = render_report_as(:html) if render_data?
|
||||
@data = Reporting::FrontendData.new(spree_current_user)
|
||||
end
|
||||
|
||||
def render_data?
|
||||
request.post?
|
||||
end
|
||||
|
||||
def render_report_as(format)
|
||||
if OpenFoodNetwork::FeatureToggle.enabled?(:background_reports, spree_current_user)
|
||||
job = ReportJob.new
|
||||
JobProcessor.perform_forked(
|
||||
job,
|
||||
report_class, spree_current_user, params, format
|
||||
)
|
||||
|
||||
# This result has been rendered by Rails in safe mode already.
|
||||
job.result.html_safe # rubocop:disable Rails/OutputSafety
|
||||
else
|
||||
@report.render_as(format)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module OrderStockCheck
|
||||
include CablecarResponses
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def valid_order_line_items?
|
||||
@@ -29,6 +30,9 @@ module OrderStockCheck
|
||||
|
||||
flash[:info] = I18n.t('order_cycle_closed')
|
||||
respond_to do |format|
|
||||
format.cable_ready {
|
||||
render status: :see_other, operations: cable_car.redirect_to(url: main_app.shop_path)
|
||||
}
|
||||
format.json { render json: { path: main_app.shop_path }, status: :see_other }
|
||||
format.html { redirect_to main_app.shop_path, status: :see_other }
|
||||
end
|
||||
|
||||
@@ -39,6 +39,14 @@ module ReportsActions
|
||||
params[:report_subtype] || report_subtypes_codes.first
|
||||
end
|
||||
|
||||
def report_title
|
||||
if report_subtype
|
||||
report_subtype_title
|
||||
else
|
||||
I18n.t(:name, scope: [:admin, :reports, report_type])
|
||||
end
|
||||
end
|
||||
|
||||
def report_subtype_title
|
||||
report_subtypes.select { |_name, key| key.to_sym == report_subtype.to_sym }.first[0]
|
||||
end
|
||||
|
||||
@@ -31,6 +31,7 @@ class SplitCheckoutController < ::BaseController
|
||||
if confirm_order || update_order
|
||||
return if performed?
|
||||
|
||||
check_payments_adjustments
|
||||
clear_invalid_payments
|
||||
advance_order_state
|
||||
redirect_to_step
|
||||
@@ -53,6 +54,10 @@ class SplitCheckoutController < ::BaseController
|
||||
flash[:error] = I18n.t('split_checkout.errors.no_shipping_methods_available')
|
||||
end
|
||||
|
||||
def check_payments_adjustments
|
||||
@order.payments.each(&:ensure_correct_adjustment)
|
||||
end
|
||||
|
||||
def clear_invalid_payments
|
||||
@order.payments.with_state(:invalid).delete_all
|
||||
end
|
||||
@@ -65,6 +70,7 @@ class SplitCheckoutController < ::BaseController
|
||||
|
||||
return true if redirect_to_payment_gateway
|
||||
|
||||
@order.process_payments!
|
||||
@order.confirm!
|
||||
order_completion_reset @order
|
||||
end
|
||||
|
||||
@@ -133,7 +133,7 @@ module Spree
|
||||
event_label = I18n.t("cancel", scope: "actions")
|
||||
button_link_to(event_label,
|
||||
fire_admin_order_url(@order, e: "cancel"),
|
||||
method: :put, icon: "icon-cancel", form_id: "cancel_order_form")
|
||||
method: :put, icon: "icon-remove", form_id: "cancel_order_form")
|
||||
end
|
||||
|
||||
def resume_event_link
|
||||
|
||||
10
app/jobs/application_job.rb
Normal file
10
app/jobs/application_job.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Rails standard class for common job code.
|
||||
class ApplicationJob < ActiveJob::Base
|
||||
# Automatically retry jobs that encountered a deadlock
|
||||
# retry_on ActiveRecord::Deadlocked
|
||||
|
||||
# Most jobs are safe to ignore if the underlying records are no longer available
|
||||
# discard_on ActiveJob::DeserializationError
|
||||
end
|
||||
@@ -1,6 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class BulkInvoiceJob < ActiveJob::Base
|
||||
class BulkInvoiceJob < ApplicationJob
|
||||
def perform(order_ids, filepath)
|
||||
pdf = CombinePDF.new
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class HeartbeatJob < ActiveJob::Base
|
||||
class HeartbeatJob < ApplicationJob
|
||||
def perform
|
||||
Spree::Config.last_job_queue_heartbeat_at = Time.now.in_time_zone
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class OrderCycleClosingJob < ActiveJob::Base
|
||||
class OrderCycleClosingJob < ApplicationJob
|
||||
def perform
|
||||
return if recently_closed_order_cycles.empty?
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Delivers an email with a report of the order cycle to each of its suppliers
|
||||
class OrderCycleNotificationJob < ActiveJob::Base
|
||||
class OrderCycleNotificationJob < ApplicationJob
|
||||
def perform(order_cycle_id)
|
||||
order_cycle = OrderCycle.find(order_cycle_id)
|
||||
order_cycle.suppliers.each do |supplier|
|
||||
|
||||
34
app/jobs/report_job.rb
Normal file
34
app/jobs/report_job.rb
Normal file
@@ -0,0 +1,34 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Renders a report and saves it to a temporary file.
|
||||
class ReportJob < ActiveJob::Base
|
||||
def perform(report_class, user, params, format)
|
||||
report = report_class.new(user, params, render: true)
|
||||
result = report.render_as(format)
|
||||
write(result)
|
||||
end
|
||||
|
||||
def done?
|
||||
@done ||= File.file?(filename)
|
||||
end
|
||||
|
||||
def result
|
||||
@result ||= read_result
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def write(result)
|
||||
File.write(filename, result)
|
||||
end
|
||||
|
||||
def read_result
|
||||
File.read(filename)
|
||||
ensure
|
||||
File.unlink(filename)
|
||||
end
|
||||
|
||||
def filename
|
||||
Rails.root.join("tmp/report-#{job_id}")
|
||||
end
|
||||
end
|
||||
@@ -3,7 +3,7 @@
|
||||
require 'order_management/subscriptions/summarizer'
|
||||
|
||||
# Confirms orders of unconfirmed proxy orders in recently closed Order Cycles
|
||||
class SubscriptionConfirmJob < ActiveJob::Base
|
||||
class SubscriptionConfirmJob < ApplicationJob
|
||||
def perform
|
||||
confirm_proxy_orders!
|
||||
end
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
require 'order_management/subscriptions/summarizer'
|
||||
|
||||
class SubscriptionPlacementJob < ActiveJob::Base
|
||||
class SubscriptionPlacementJob < ApplicationJob
|
||||
def perform
|
||||
proxy_orders.each do |proxy_order|
|
||||
place_order_for(proxy_order)
|
||||
|
||||
@@ -15,6 +15,7 @@ class Enterprise < ApplicationRecord
|
||||
medium: { resize_to_fill: [720, 156] },
|
||||
large: { resize_to_fill: [1200, 260] },
|
||||
}.freeze
|
||||
VALID_INSTAGRAM_REGEX = %r{\A[a-zA-Z0-9._]{1,30}([^/-]*)\z}
|
||||
|
||||
searchable_attributes :sells, :is_primary_producer
|
||||
searchable_associations :properties
|
||||
@@ -99,6 +100,7 @@ class Enterprise < ApplicationRecord
|
||||
validate :shopfront_taxons
|
||||
validate :shopfront_producers
|
||||
validate :enforce_ownership_limit, if: lambda { owner_id_changed? && !owner_id.nil? }
|
||||
validates :instagram, format: { with: VALID_INSTAGRAM_REGEX, message: Spree.t('errors.messages.invalid_instagram_url') }, allow_blank: true
|
||||
|
||||
before_validation :initialize_permalink, if: lambda { permalink.nil? }
|
||||
before_validation :set_unused_address_fields
|
||||
@@ -456,7 +458,7 @@ class Enterprise < ApplicationRecord
|
||||
end
|
||||
|
||||
def correct_instagram_url(url)
|
||||
url && strip_url(url).sub(%r{www.instagram.com/}, '').delete("@")
|
||||
url && strip_url(url.downcase).sub(%r{www.instagram.com/}, '').sub(%r{instagram.com/}, '').delete("@")
|
||||
end
|
||||
|
||||
def correct_twitter_url(url)
|
||||
|
||||
@@ -211,7 +211,7 @@ module ProductImport
|
||||
reference_entry = all_entries_for_product(entry).first
|
||||
return if entry.variant_unit_name.to_s == reference_entry.variant_unit_name.to_s
|
||||
|
||||
mark_as_not_updatable(entry, "variant_unit_name")
|
||||
mark_as_values_must_be_same(entry, "variant_unit_name")
|
||||
end
|
||||
|
||||
def producer_validation(entry)
|
||||
@@ -425,6 +425,11 @@ module ProductImport
|
||||
error: I18n.t("admin.product_import.model.not_updatable"))
|
||||
end
|
||||
|
||||
def mark_as_values_must_be_same(entry, attribute)
|
||||
mark_as_invalid(entry, attribute: attribute,
|
||||
error: I18n.t("admin.product_import.model.values_must_be_same"))
|
||||
end
|
||||
|
||||
def import_into_inventory?
|
||||
@import_settings.dig(:settings, 'import_into') == 'inventories'
|
||||
end
|
||||
|
||||
@@ -16,4 +16,11 @@ class ApplicationReflex < StimulusReflex::Reflex
|
||||
#
|
||||
# For code examples, considerations and caveats, see:
|
||||
# https://docs.stimulusreflex.com/rtfm/patterns#internationalization
|
||||
include CanCan::ControllerAdditions
|
||||
|
||||
delegate :current_user, to: :connection
|
||||
|
||||
def current_ability
|
||||
Spree::Ability.new(current_user)
|
||||
end
|
||||
end
|
||||
|
||||
13
app/reflexes/resend_confirmation_email_reflex.rb
Normal file
13
app/reflexes/resend_confirmation_email_reflex.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ResendConfirmationEmailReflex < ApplicationReflex
|
||||
def confirm(order_ids)
|
||||
Spree::Order.where(id: order_ids).find_each do |o|
|
||||
Spree::OrderMailer.confirm_email_for_customer(o.id, true).deliver_later if can? :resend, o
|
||||
end
|
||||
|
||||
flash[:success] = I18n.t("admin.resend_confirmation_emails_feedback", count: order_ids.count)
|
||||
cable_ready.dispatch_event(name: "modal:close")
|
||||
morph "#flashes", render(partial: "shared/flashes", locals: { flashes: flash })
|
||||
end
|
||||
end
|
||||
29
app/services/job_processor.rb
Normal file
29
app/services/job_processor.rb
Normal file
@@ -0,0 +1,29 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Forks into a separate process to contain memory usage and timeout errors.
|
||||
class JobProcessor
|
||||
def self.perform_forked(job, *args)
|
||||
# Reports should abort when puma threads are killed to avoid wasting
|
||||
# resources. Nobody would be collecting the result. We still need to
|
||||
# implement a way to email or download reports later.
|
||||
timeout = ENV.fetch("RACK_TIMEOUT_WAIT_TIMEOUT", "30").to_i
|
||||
|
||||
child = fork do
|
||||
Process.setproctitle("Job worker #{job.job_id}")
|
||||
Timeout.timeout(timeout) do
|
||||
job.perform(*args)
|
||||
end
|
||||
|
||||
# Exit is not a good idea within a Rails process but Rubocop doesn't know
|
||||
# that we are in a forked process.
|
||||
exit # rubocop:disable Rails/Exit
|
||||
end
|
||||
|
||||
# Wait for all forked child processes to exit
|
||||
Process.waitall
|
||||
ensure
|
||||
# If this Puma thread is interrupted then we need to detach the child
|
||||
# process to avoid it becoming a zombie.
|
||||
Process.detach(child)
|
||||
end
|
||||
end
|
||||
@@ -102,7 +102,6 @@
|
||||
%td.actions
|
||||
%a{ 'ng-click' => "deleteCustomer(customer)", :class => "delete-customer icon-trash no-text" }
|
||||
|
||||
-# %show-more.text-center{ data: "filteredCustomers", limit: "customerLimit", increment: "20" }
|
||||
%div.text-center{ ng: { show: "filteredCustomers.length > customerLimit" } }
|
||||
%input{ type: 'button', value: t(:show_more), ng: { click: 'customerLimit = customerLimit + 20' } }
|
||||
%input{ type: 'button', value: t(:show_all_with_more, num: '{{ filteredCustomers.length - customerLimit }}'), ng: { click: 'customerLimit = filteredCustomers.length' } }
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
{{ enterprise.name }}
|
||||
= "{{ enterprise.issues_summary_#{type} ? '('+enterprise.issues_summary_#{type}+')' : '' }}"
|
||||
|
||||
= f.submit t(".add_#{type}"), 'ng-click' => "add#{type.capitalize}($event)", 'ng-disabled' => "!new_#{type}_id || !OrderCycle.novel#{type.capitalize}(new_#{type}_id)"
|
||||
= f.submit t(".add_#{type}"), 'ng-click' => "add#{type.capitalize}($event)", 'ng-disabled' => "!new_#{type}_id || !OrderCycle.novel#{type.capitalize}(new_#{type}_id)", "class": "secondary"
|
||||
|
||||
@@ -26,15 +26,16 @@
|
||||
|
||||
= f.submit t('.add_fee'), 'ng-click' => 'addExchangeFee($event, exchange)', 'ng-hide' => '!enterprises[exchange.enterprise_id].managed && !order_cycle.viewing_as_coordinator'
|
||||
%td.actions
|
||||
%a{'ng-click' => 'removeExchange($event, exchange)', :class => "icon-trash no-text remove-exchange"}
|
||||
.flex
|
||||
%a{'ng-click' => 'removeExchange($event, exchange)', :class => "icon-trash no-text remove-exchange"}
|
||||
|
||||
- if type == 'supplier'
|
||||
%tr.panel-row{ object: "exchange",
|
||||
panels: "{products: 'exchange_products_supplied'}",
|
||||
locals: "$index,exchangeTotalVariants,order_cycle,exchange,enterprises,setExchangeVariants,selectAllVariants,suppliedVariants,removeDistributionOfVariant,initializeExchangeProductsPanel,loadMoreExchangeProducts,loadAllExchangeProducts,productsLoading",
|
||||
colspan: 4 }
|
||||
colspan: if feature?(:admin_style_v2, spree_current_user) then 5 else 4 end }
|
||||
- if type == 'distributor'
|
||||
%tr.panel-row{ object: "exchange",
|
||||
panels: "{products: 'exchange_products_distributed', tags: 'exchange_tags'}",
|
||||
locals: "$index,exchangeTotalVariants,order_cycle,exchange,enterprises,setExchangeVariants,incomingExchangeVariantsFor,variantSuppliedToOrderCycle,initializeExchangeProductsPanel,loadMoreExchangeProducts,loadAllExchangeProducts,productsLoading",
|
||||
colspan: 5 }
|
||||
colspan: if feature?(:admin_style_v2, spree_current_user) then 6 else 5 end }
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
%colgroup
|
||||
%col{ ng: { show: 'columns.name.visible' } }
|
||||
%col{ ng: { show: 'columns.schedules.visible' } }
|
||||
%col{ ng: { show: 'columns.open.visible' }, style: 'width: 20%;' }
|
||||
%col{ ng: { show: 'columns.close.visible' }, style: 'width: 20%;' }
|
||||
%col{ ng: { show: 'columns.open.visible' } }
|
||||
%col{ ng: { show: 'columns.close.visible' } }
|
||||
- unless simple_index
|
||||
%col{ ng: { show: 'columns.producers.visible' } }
|
||||
%col{ ng: { show: 'columns.coordinator.visible' } }
|
||||
%col{ ng: { show: 'columns.shops.visible' } }
|
||||
%col{ ng: { show: 'columns.products.visible' } }
|
||||
%col{ style: 'width: 5%;' }
|
||||
%col{ style: 'width: 5%;' }
|
||||
%col{ style: 'width: 5%;' }
|
||||
%col
|
||||
%col
|
||||
%col
|
||||
|
||||
%thead
|
||||
%tr
|
||||
@@ -32,5 +32,3 @@
|
||||
%th{ ng: { show: 'columns.products.visible' } }
|
||||
=t :products
|
||||
%th.actions
|
||||
%th.actions
|
||||
%th.actions
|
||||
|
||||
@@ -32,8 +32,9 @@
|
||||
= t('.variants')
|
||||
|
||||
%td.actions
|
||||
%a.edit-order-cycle.icon-edit.no-text{ ng: { href: '{{orderCycle.edit_path}}'}, 'ofn-with-tip' => t(:edit) }
|
||||
%td.actions{ ng: { if: 'orderCycle.viewing_as_coordinator' } }
|
||||
%a.clone-order-cycle.icon-copy.no-text{ ng: { href: '{{orderCycle.clone_path}}'}, 'ofn-with-tip' => t(:clone) }
|
||||
%td.actions{ ng: { if: 'orderCycle.deletable && orderCycle.viewing_as_coordinator' }}
|
||||
%a.delete-order-cycle.icon-trash.no-text{ ng: { href: '{{orderCycle.delete_path}}'}, data: { method: 'delete', confirm: t(:are_you_sure) }, 'ofn-with-tip' => t(:remove) }
|
||||
.flex
|
||||
%a.edit-order-cycle.icon-edit.no-text{ ng: { href: '{{orderCycle.edit_path}}'}, 'ofn-with-tip' => t(:edit) }
|
||||
%div{ ng: { if: 'orderCycle.viewing_as_coordinator' } }
|
||||
%a.clone-order-cycle.icon-copy.no-text{ ng: { href: '{{orderCycle.clone_path}}'}, 'ofn-with-tip' => t(:clone) }
|
||||
%div{ ng: { if: 'orderCycle.deletable && orderCycle.viewing_as_coordinator' }}
|
||||
%a.delete-order-cycle.icon-trash.no-text{ ng: { href: '{{orderCycle.delete_path}}'}, data: { method: 'delete', confirm: t(:are_you_sure) }, 'ofn-with-tip' => t(:remove) }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
%ul{style: "margin-left: 12pt"}
|
||||
- report_subtypes.each do |report_subtype|
|
||||
%li
|
||||
- url = main_app.admin_report_url(report_type: report_type, report_subtype: report_subtype[1])
|
||||
- url = main_app.admin_report_path(report_type: report_type, report_subtype: report_subtype[1])
|
||||
= link_to report_subtype[0], url
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
- report ||= @report
|
||||
|
||||
.report__table-container
|
||||
%table.report__table
|
||||
%thead
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
- content_for :page_title do
|
||||
= @report_title
|
||||
|
||||
= form_for @report.search, :url => url_for(only_path: false) do |f|
|
||||
= form_for @report.search, :url => url_for do |f|
|
||||
%fieldset.no-border-bottom.print-hidden
|
||||
%legend{ align: 'center'}= t(:report_filters)
|
||||
= render partial: "admin/reports/filters/#{@report_type}", locals: { f: f }
|
||||
@@ -19,7 +19,4 @@
|
||||
- if request.post?
|
||||
%button.btn-print.icon-print{ onclick: "window.print()"}= t(:report_print)
|
||||
|
||||
/ We don't want to render data unless search params are supplied.
|
||||
/ Compiling data can take a long time.
|
||||
- if request.post?
|
||||
= render "table"
|
||||
= @table
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
-# %show-more.text-center{ data: "filteredProducts", limit: "productLimit", increment: "10" }
|
||||
.text-center{ ng: { show: "filteredProducts.length > productLimit" } }
|
||||
%input{ type: 'button', value: t(:show_more), ng: { click: 'productLimit = productLimit + 10' } }
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.small-12.medium-6.columns.text-right
|
||||
|
||||
|
||||
.row.animate-show.filter-row{"ng-show" => "filtersActive"}
|
||||
.row.animate-show{"ng-show" => "filtersActive"}
|
||||
.small-12.columns
|
||||
.row.filter-box
|
||||
.small-12.columns
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
- if defined? flashes
|
||||
- flashes.each do |type, msg|
|
||||
%alert.animate-show{"data-controller": "flash"}
|
||||
%div{type: "#{type}", class: "alert-box #{type == 'error' ? 'alert' : type}"}
|
||||
.flash{type: "#{type}", class: "alert-box #{type == 'error' ? 'alert' : type}"}
|
||||
%span= msg
|
||||
%a.small.close{"data-action": "click->flash#close"} ×
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
.row
|
||||
= render 'shared/components/filter_controls'
|
||||
|
||||
.row.animate-show.filter-row{"ng-show" => "filtersActive"}
|
||||
.row.animate-show{"ng-show" => "filtersActive"}
|
||||
.small-12.columns
|
||||
.row.filter-box
|
||||
.small-12.large-9.columns
|
||||
|
||||
@@ -3,51 +3,53 @@
|
||||
%div.checkout-substep
|
||||
-# YOUR DETAILS
|
||||
%div.checkout-title
|
||||
= t("split_checkout.step1.your_details.title")
|
||||
= t("split_checkout.step1.contact_information.title")
|
||||
|
||||
%div.checkout-input
|
||||
= bill_address.label :firstname, t("split_checkout.step1.your_details.first_name.label")
|
||||
= bill_address.text_field :firstname, { placeholder: t("split_checkout.step1.your_details.first_name.placeholder") }
|
||||
= f.error_message_on "bill_address.firstname"
|
||||
.two-columns-inputs
|
||||
%div.checkout-input.with-floating-label{ "data-controller": "floating-label" }
|
||||
= f.label :email, t("split_checkout.step1.contact_information.email.label")
|
||||
= f.text_field :email, { placeholder: " " }
|
||||
= f.error_message_on :email
|
||||
|
||||
%div.checkout-input
|
||||
= bill_address.label :lastname, t("split_checkout.step1.your_details.last_name.label")
|
||||
= bill_address.text_field :lastname, { placeholder: t("split_checkout.step1.your_details.last_name.placeholder") }
|
||||
= f.error_message_on "bill_address.lastname"
|
||||
|
||||
%div.checkout-input
|
||||
= f.label :email, t("split_checkout.step1.your_details.email.label")
|
||||
= f.text_field :email, { placeholder: t("split_checkout.step1.your_details.email.placeholder") }
|
||||
= f.error_message_on :email
|
||||
|
||||
%div.checkout-input
|
||||
= bill_address.label :phone, t("split_checkout.step1.your_details.phone.label")
|
||||
= bill_address.text_field :phone, { placeholder: t("split_checkout.step1.your_details.phone.placeholder") }
|
||||
= f.error_message_on "bill_address.phone"
|
||||
%div.checkout-input.with-floating-label{ "data-controller": "floating-label" }
|
||||
= bill_address.label :phone, t("split_checkout.step1.contact_information.phone.label")
|
||||
= bill_address.text_field :phone, { placeholder: " " }
|
||||
= f.error_message_on "bill_address.phone"
|
||||
|
||||
%div.checkout-substep
|
||||
-# BILLING ADDRESS
|
||||
%div.checkout-title
|
||||
= t("split_checkout.step1.billing_address.title")
|
||||
|
||||
%div.checkout-input
|
||||
.two-columns-inputs
|
||||
%div.checkout-input.with-floating-label{ "data-controller": "floating-label" }
|
||||
= bill_address.label :firstname, t("split_checkout.step1.billing_address.first_name.label")
|
||||
= bill_address.text_field :firstname, { placeholder: " " }
|
||||
= f.error_message_on "bill_address.firstname"
|
||||
|
||||
%div.checkout-input.with-floating-label{ "data-controller": "floating-label" }
|
||||
= bill_address.label :lastname, t("split_checkout.step1.billing_address.last_name.label")
|
||||
= bill_address.text_field :lastname, { placeholder: " " }
|
||||
= f.error_message_on "bill_address.lastname"
|
||||
|
||||
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
|
||||
= bill_address.label :address1, t("split_checkout.step1.address.address1.label")
|
||||
= bill_address.text_field :address1, { placeholder: t("split_checkout.step1.address.address1.placeholder") }
|
||||
= bill_address.text_field :address1, { placeholder: " " }
|
||||
= f.error_message_on "bill_address.address1"
|
||||
|
||||
%div.checkout-input
|
||||
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
|
||||
= bill_address.label :address2, t("split_checkout.step1.address.address2.label")
|
||||
= bill_address.text_field :address2, { placeholder: t("split_checkout.step1.address.address2.placeholder") }
|
||||
= bill_address.text_field :address2, { placeholder: " " }
|
||||
= f.error_message_on "bill_address.address2"
|
||||
|
||||
%div.checkout-input
|
||||
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
|
||||
= bill_address.label :city, t("split_checkout.step1.address.city.label")
|
||||
= bill_address.text_field :city, { placeholder: t("split_checkout.step1.address.city.placeholder") }
|
||||
= bill_address.text_field :city, { placeholder: " " }
|
||||
= f.error_message_on "bill_address.city"
|
||||
|
||||
%div.checkout-input
|
||||
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
|
||||
= bill_address.label :zipcode, t("split_checkout.step1.address.zipcode.label")
|
||||
= bill_address.text_field :zipcode, { placeholder: t("split_checkout.step1.address.zipcode.placeholder") }
|
||||
= bill_address.text_field :zipcode, { placeholder: " " }
|
||||
= f.error_message_on "bill_address.zipcode"
|
||||
|
||||
%div{ "data-controller": "dependent-select", "data-dependent-select-options-value": countries_with_states }
|
||||
@@ -76,33 +78,30 @@
|
||||
|
||||
- selected_shipping_method ||= @shipping_methods[0].id if @shipping_methods.length == 1
|
||||
- @shipping_methods.each do |shipping_method|
|
||||
- ship_method_is_selected = shipping_method.id == selected_shipping_method.to_i
|
||||
%div.checkout-input.checkout-input-radio
|
||||
= fields_for shipping_method do |shipping_method_form|
|
||||
= shipping_method_form.radio_button :name, shipping_method.id,
|
||||
id: "shipping_method_#{shipping_method.id}",
|
||||
checked: (shipping_method.id == selected_shipping_method.to_i),
|
||||
checked: ship_method_is_selected,
|
||||
name: "shipping_method_id",
|
||||
"data-description": shipping_method.description,
|
||||
"data-requireAddress": shipping_method.require_ship_address,
|
||||
"data-action": "toggle#toggle shippingmethod#selectShippingMethod",
|
||||
"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.light
|
||||
= payment_or_shipping_price(shipping_method, @order)
|
||||
- display_ship_address = display_ship_address || (shipping_method.id == selected_shipping_method.to_i && shipping_method.require_ship_address)
|
||||
- if shipping_method.id == selected_shipping_method.to_i
|
||||
- ship_method_description = shipping_method.description
|
||||
|
||||
%em= payment_or_shipping_price(shipping_method, @order)
|
||||
- display_ship_address = display_ship_address || (ship_method_is_selected && shipping_method.require_ship_address)
|
||||
%div.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?
|
||||
%span #{shipping_method.description}
|
||||
%br/
|
||||
%br/
|
||||
- if @order.order_cycle.pickup_time_for(@order.distributor)
|
||||
= t :checkout_ready_for
|
||||
= @order.order_cycle.pickup_time_for(@order.distributor)
|
||||
|
||||
= f.error_message_on :shipping_method, standalone: true
|
||||
|
||||
%div.checkout-input{"data-shippingmethod-target": "shippingMethodDescription", style: "display: #{ship_method_description == nil ? 'none' : 'block'}" }
|
||||
#distributor_address.panel
|
||||
%span{"data-shippingmethod-target": "shippingMethodDescriptionContent"} #{ship_method_description}
|
||||
%br/
|
||||
%br/
|
||||
- if @order.order_cycle.pickup_time_for(@order.distributor)
|
||||
= t :checkout_ready_for
|
||||
= @order.order_cycle.pickup_time_for(@order.distributor)
|
||||
|
||||
%div.checkout-input{ "data-toggle-target": "content", style: "display: #{display_ship_address ? 'block' : 'none'}" }
|
||||
= f.check_box :ship_address_same_as_billing, { id: "ship_address_same_as_billing", name: "ship_address_same_as_billing", "data-action": "shippingmethod#showHideShippingAddress", "data-shippingmethod-target": "shippingAddressCheckbox", checked: shipping_and_billing_match?(@order) }, 1, nil
|
||||
@@ -110,24 +109,24 @@
|
||||
|
||||
%div{"data-shippingmethod-target": "shippingMethodAddress", style: "display: #{!display_ship_address || shipping_and_billing_match?(@order) ? 'none' : 'block'}" }
|
||||
= f.fields :ship_address, model: @order.ship_address do |ship_address|
|
||||
%div.checkout-input
|
||||
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
|
||||
= ship_address.label :address1, t("split_checkout.step1.address.address1.label")
|
||||
= ship_address.text_field :address1, { placeholder: t("split_checkout.step1.address.address1.placeholder") }
|
||||
= ship_address.text_field :address1, { placeholder: " " }
|
||||
= f.error_message_on "ship_address.address1"
|
||||
|
||||
%div.checkout-input
|
||||
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
|
||||
= ship_address.label :address2, t("split_checkout.step1.address.address2.label")
|
||||
= ship_address.text_field :address2, { placeholder: t("split_checkout.step1.address.address2.placeholder") }
|
||||
= ship_address.text_field :address2, { placeholder: " " }
|
||||
= f.error_message_on "ship_address.address2"
|
||||
|
||||
%div.checkout-input
|
||||
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
|
||||
= ship_address.label :city, t("split_checkout.step1.address.city.label")
|
||||
= ship_address.text_field :city, { placeholder: t("split_checkout.step1.address.city.placeholder") }
|
||||
= ship_address.text_field :city, { placeholder: " " }
|
||||
= f.error_message_on "ship_address.city"
|
||||
|
||||
%div.checkout-input
|
||||
%div.checkout-input.with-floating-label{ "data-controller": "floating-label"}
|
||||
= ship_address.label :zipcode, t("split_checkout.step1.address.zipcode.label")
|
||||
= ship_address.text_field :zipcode, { placeholder: t("split_checkout.step1.address.zipcode.placeholder") }
|
||||
= ship_address.text_field :zipcode, { placeholder: " " }
|
||||
= f.error_message_on "ship_address.zipcode"
|
||||
|
||||
%div{ "data-controller": "dependent-select", "data-dependent-select-options-value": countries_with_states }
|
||||
|
||||
@@ -14,19 +14,18 @@
|
||||
"data-action": "paymentmethod#selectPaymentMethod",
|
||||
"data-paymentmethod-id": "paymentmethod#{payment_method.id}",
|
||||
"data-paymentmethod-target": "input"
|
||||
= f.label :payment_method_id, "#{payment_method.name} (#{payment_or_shipping_price(payment_method, @order)})", for: "payment_method_#{payment_method.id}"
|
||||
= f.label :payment_method_id, "#{payment_method.name}", for: "payment_method_#{payment_method.id}"
|
||||
%em=payment_or_shipping_price(payment_method, @order)
|
||||
|
||||
= f.error_message_on :payment_method, standalone: true
|
||||
|
||||
- available_payment_methods.each do |payment_method|
|
||||
.paymentmethod-container{id: "paymentmethod#{payment_method.id}", style: "display: #{payment_method.id == selected_payment_method ? "block" : "none"}"}
|
||||
.paymentmethod-container{"data-paymentmethod-id": "paymentmethod#{payment_method.id}", style: "display: #{payment_method.id == selected_payment_method ? "block" : "none"}"}
|
||||
- if payment_method.description && !payment_method.description.empty?
|
||||
.paymentmethod-description.panel
|
||||
#{payment_method.description}
|
||||
|
||||
.paymentmethod-form
|
||||
= render partial: "split_checkout/payment/#{payment_method.method_type}", locals: { payment_method: payment_method, f: f }
|
||||
|
||||
|
||||
= f.error_message_on :payment_method, standalone: true
|
||||
|
||||
%div.checkout-substep
|
||||
= t("split_checkout.step2.explaination")
|
||||
|
||||
|
||||
@@ -5,25 +5,25 @@
|
||||
|
||||
%div.summary
|
||||
%span.summary-label
|
||||
= t("split_checkout.step1.your_details.first_name.label")
|
||||
= t("split_checkout.step1.billing_address.first_name.label")
|
||||
%span.summary-value
|
||||
= @order.bill_address.firstname
|
||||
|
||||
%div.summary
|
||||
%span.summary-label
|
||||
= t("split_checkout.step1.your_details.last_name.label")
|
||||
= t("split_checkout.step1.billing_address.last_name.label")
|
||||
%span.summary-value
|
||||
= @order.bill_address.lastname
|
||||
|
||||
%div.summary
|
||||
%span.summary-label
|
||||
= t("split_checkout.step1.your_details.email.label")
|
||||
= t("split_checkout.step1.contact_information.email.label")
|
||||
%span.summary-value
|
||||
= @order.user ? @order.user.email : "Change me"
|
||||
|
||||
%div.summary
|
||||
%span.summary-label
|
||||
= t("split_checkout.step1.your_details.phone.label")
|
||||
= t("split_checkout.step1.contact_information.phone.label")
|
||||
%span.summary-value
|
||||
= @order.bill_address.phone
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
= t(".no_note_present")
|
||||
|
||||
%td.actions
|
||||
= link_to '', '', class: 'edit-note icon_link icon-edit no-text with-tip', data: { action: 'edit' }, title: Spree.t('edit')
|
||||
- if @order.note.present?
|
||||
= link_to '', '', class: 'delete-note icon_link icon-trash no-text with-tip', data: { action: 'remove' }, title: Spree.t('delete')
|
||||
.flex
|
||||
= link_to '', '', class: 'edit-note icon_link icon-edit no-text with-tip', data: { action: 'edit' }, title: Spree.t('edit')
|
||||
- if @order.note.present?
|
||||
= link_to '', '', class: 'delete-note icon_link icon-trash no-text with-tip', data: { action: 'remove' }, title: Spree.t('delete')
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
= Spree.t(:price)
|
||||
%th
|
||||
= Spree.t(:quantity)
|
||||
%th
|
||||
%th.force-rounded-right
|
||||
= Spree.t(:total)
|
||||
%th.orders-actions.actions{ "data-hook" => "admin_order_form_line_items_header_actions" }
|
||||
|
||||
@@ -57,8 +57,8 @@
|
||||
%span
|
||||
= shipment.fee_adjustment.display_amount
|
||||
|
||||
- if shipment.fee_adjustment.present? && shipment.can_modify?
|
||||
%td.actions
|
||||
%td.actions
|
||||
- if shipment.fee_adjustment.present? && shipment.can_modify?
|
||||
- if can? :update, shipment
|
||||
= link_to '', '', :class => 'edit-method icon_link icon-edit no-text with-tip', :data => { :action => 'edit' }, :title => Spree.t('edit')
|
||||
|
||||
@@ -70,8 +70,9 @@
|
||||
|
||||
%td.actions
|
||||
- if can?(:update, shipment) && !shipment.canceled?
|
||||
= link_to '', '', :class => 'save-tracking icon_link icon-ok no-text with-tip', :data => { 'shipment-number' => shipment.number, :action => 'save' }, :title => I18n.t('actions.save')
|
||||
= link_to '', '', :class => 'cancel-tracking icon_link icon-cancel no-text with-tip', :data => { :action => 'cancel' }, :title => I18n.t('actions.cancel')
|
||||
.flex
|
||||
= link_to '', '', :class => 'save-tracking icon_link icon-ok no-text with-tip', :data => { 'shipment-number' => shipment.number, :action => 'save' }, :title => I18n.t('actions.save')
|
||||
= link_to '', '', :class => 'cancel-tracking icon_link icon-cancel no-text with-tip', :data => { :action => 'cancel' }, :title => I18n.t('actions.cancel')
|
||||
|
||||
%tr.show-tracking.total
|
||||
%td{ :colspan => "5" }
|
||||
@@ -84,6 +85,7 @@
|
||||
|
||||
%td.actions
|
||||
- if can?(:update, shipment) && shipment.can_modify?
|
||||
= link_to '', '', :class => 'edit-tracking icon_link icon-edit no-text with-tip', :data => { :action => 'edit' }, :title => Spree.t('edit')
|
||||
- if shipment.tracking.present?
|
||||
= link_to '', '', :class => 'delete-tracking icon_link icon-trash no-text with-tip', :data => { 'shipment-number' => shipment.number, :action => 'remove' }, :title => Spree.t('delete')
|
||||
.flex
|
||||
= link_to '', '', :class => 'edit-tracking icon_link icon-edit no-text with-tip', :data => { :action => 'edit' }, :title => Spree.t('edit')
|
||||
- if shipment.tracking.present?
|
||||
= link_to '', '', :class => 'delete-tracking icon_link icon-trash no-text with-tip', :data => { 'shipment-number' => shipment.number, :action => 'remove' }, :title => Spree.t('delete')
|
||||
|
||||
@@ -19,10 +19,11 @@
|
||||
|
||||
%td.cart-item-delete.actions{ "data-hook" => "cart_item_delete" }
|
||||
- if shipment.can_modify? && can?(:update, shipment)
|
||||
= link_to '', '#', :class => 'save-item icon_link icon-ok no-text with-tip', :data => {'shipment-number' => shipment.number, 'variant-id' => item.variant.id, :action => 'save'}, :title => t('actions.save'), :style => 'display: none'
|
||||
= link_to '', '#', :class => 'cancel-item icon_link icon-cancel no-text with-tip', :data => {:action => 'cancel'}, :title => t('actions.cancel'), :style => 'display: none'
|
||||
= link_to '', '#', :class => 'edit-item icon_link icon-edit no-text with-tip', :data => {:action => 'edit'}, :title => t('actions.edit')
|
||||
= link_to '', '#', :class => 'delete-item icon-trash no-text with-tip', :data => {'shipment-number' => shipment.number, 'variant-id' => item.variant.id, :action => 'remove'}, :title => t('actions.delete')
|
||||
.flex
|
||||
= link_to '', '#', :class => 'save-item icon_link icon-ok no-text with-tip', :data => {'shipment-number' => shipment.number, 'variant-id' => item.variant.id, :action => 'save'}, :title => t('actions.save'), :style => 'display: none'
|
||||
= link_to '', '#', :class => 'cancel-item icon_link icon-cancel no-text with-tip', :data => {:action => 'cancel'}, :title => t('actions.cancel'), :style => 'display: none'
|
||||
= link_to '', '#', :class => 'edit-item icon_link icon-edit no-text with-tip', :data => {:action => 'edit'}, :title => t('actions.edit')
|
||||
= link_to '', '#', :class => 'delete-item icon-trash no-text with-tip', :data => {'shipment-number' => shipment.number, 'variant-id' => item.variant.id, :action => 'remove'}, :title => t('actions.delete')
|
||||
|
||||
= render 'spree/admin/shared/custom-alert'
|
||||
= render 'spree/admin/shared/custom-confirm'
|
||||
|
||||
@@ -12,39 +12,42 @@
|
||||
= admin_inject_column_preferences module: 'admin.lineItems'
|
||||
= admin_inject_available_units
|
||||
|
||||
%div{ ng: { controller: 'LineItemsCtrl' } }
|
||||
%save-bar{ dirty: "bulk_order_form.$dirty", persist: "false" }
|
||||
%input.red{ type: "button", value: "Save Changes", ng: { click: "submit()", disabled: "!bulk_order_form.$dirty" } }
|
||||
|
||||
.filters{ :class => "sixteen columns alpha" }
|
||||
.date_filter{class: "four columns"}
|
||||
%label
|
||||
= t("date_range")
|
||||
%br
|
||||
%div{ data: { controller: "flatpickr", "flatpickr-mode-value": "range", "flatpickr-default-date": "{{ [startDate, endDate] }}" } }
|
||||
%input.datepicker.fullwidth{ class: "datepicker", data: { "flatpickr-target": "instance" } }
|
||||
%input{ type: "text", id: 'start_date_filter', 'ng-model': "startDate", data: { "flatpickr-target": "start" }, style: "display: none;" }
|
||||
%input{ type: "text", id: 'end_date_filter', 'ng-model': "endDate", data: { "flatpickr-target": "end" }, style: "display: none;" }
|
||||
.one.column
|
||||
.filter_select{ :class => "three columns" }
|
||||
%label{ :for => 'supplier_filter' }
|
||||
= t("admin.producer")
|
||||
%br
|
||||
%input#supplier_filter.ofn-select2.fullwidth{ type: 'number', 'min-search' => 5, data: 'suppliers', placeholder: "#{t(:all)}", blank: "{ id: '', name: '#{t(:all)}' }", on: { selecting: "confirmRefresh" }, ng: { model: 'supplierFilter', change: 'refreshData()' } }
|
||||
.filter_select{ :class => "three columns" }
|
||||
%label{ :for => 'distributor_filter' }
|
||||
= t("admin.shop")
|
||||
%br
|
||||
%input#distributor_filter.ofn-select2.fullwidth{ type: 'number', 'min-search' => 5, data: 'distributors', placeholder: "#{t(:all)}", blank: "{ id: '', name: '#{t(:all)}' }", on: { selecting: "confirmRefresh" }, ng: { model: 'distributorFilter', change: 'refreshData()' } }
|
||||
.filter_select{ :class => "three columns" }
|
||||
%label{ :for => 'order_cycle_filter' }
|
||||
= t("admin.order_cycle")
|
||||
%br
|
||||
%input#order_cycle_filter.ofn-select2.fullwidth{ type: 'number', 'min-search' => 5, data: 'orderCycles', placeholder: "#{t(:all)}", blank: "{ id: '', name: '#{t(:all)}' }", on: { selecting: "confirmRefresh" }, ng: { model: 'orderCycleFilter', change: 'refreshData()' } }
|
||||
.filter_clear{ :class => "two columns omega" }
|
||||
%label{ :for => 'clear_all_filters' }
|
||||
%br
|
||||
%input.red.fullwidth{ :type => 'button', :id => 'clear_all_filters', :value => t('admin.clear_all'), 'ng-click' => "resetSelectFilters()" }
|
||||
%div{ ng: { controller: 'LineItemsCtrl' }, id: "table-filter" }
|
||||
%fieldset
|
||||
%save-bar{ dirty: "bulk_order_form.$dirty", persist: "false" }
|
||||
%input.red{ type: "button", value: "Save Changes", ng: { click: "submit()", disabled: "!bulk_order_form.$dirty" } }
|
||||
%legend{ align: 'center'}= t(:search)
|
||||
%div{ :class => "sixteen columns alpha" }
|
||||
.filter_select{ :class => "four columns" }
|
||||
%label{ :for => 'supplier_filter' }
|
||||
= t("admin.producer")
|
||||
%br
|
||||
%input#supplier_filter.ofn-select2.fullwidth{ type: 'number', 'min-search' => 5, data: 'suppliers', placeholder: "#{t(:all)}", blank: "{ id: '', name: '#{t(:all)}' }", on: { selecting: "confirmRefresh" }, ng: { model: 'supplierFilter' } }
|
||||
.filter_select{ :class => "four columns" }
|
||||
%label{ :for => 'distributor_filter' }
|
||||
= t("admin.shop")
|
||||
%br
|
||||
%input#distributor_filter.ofn-select2.fullwidth{ type: 'number', 'min-search' => 5, data: 'distributors', placeholder: "#{t(:all)}", blank: "{ id: '', name: '#{t(:all)}' }", on: { selecting: "confirmRefresh" }, ng: { model: 'distributorFilter' } }
|
||||
.filter_select{ :class => "four columns" }
|
||||
%label{ :for => 'order_cycle_filter' }
|
||||
= t("admin.order_cycle")
|
||||
%br
|
||||
%input#order_cycle_filter.ofn-select2.fullwidth{ type: 'number', 'min-search' => 5, data: 'orderCycles', placeholder: "#{t(:all)}", blank: "{ id: '', name: '#{t(:all)}' }", on: { selecting: "confirmRefresh" }, ng: { model: 'orderCycleFilter', change: "setOrderCycleDateRange()" } }
|
||||
.date_filter{class: "four columns"}
|
||||
%label
|
||||
= t("date_range")
|
||||
%br
|
||||
%div{ data: { controller: "flatpickr", "flatpickr-mode-value": "range", "flatpickr-default-date": "{{ [startDate, endDate] }}" } }
|
||||
%input.datepicker.fullwidth{ class: "datepicker", data: { "flatpickr-target": "instance" } }
|
||||
%input{ type: "text", id: 'start_date_filter', 'ng-model': "startDate", data: { "flatpickr-target": "start" }, style: "display: none;" }
|
||||
%input{ type: "text", id: 'end_date_filter', 'ng-model': "endDate", data: { "flatpickr-target": "end" }, style: "display: none;" }
|
||||
|
||||
.clearfix
|
||||
.actions.filter-actions
|
||||
%a.button.icon-search{'ng-click' => 'refreshData()'}
|
||||
= t(:filter_results)
|
||||
%a.button{'ng-click' => 'resetSelectFilters()', "id": "clear_filters_button", "class": ("secondary" if feature?(:admin_style_v2, spree_current_user)) }
|
||||
= t(:clear_filters)
|
||||
|
||||
%hr.divider.sixteen.columns.alpha.omega{ ng: { show: 'unitsVariantSelected()' } }
|
||||
|
||||
|
||||
@@ -30,13 +30,15 @@
|
||||
="#{t('admin.actions')}".html_safe
|
||||
%span{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" }
|
||||
%div.menu{ 'ng-show' => "expanded" }
|
||||
%div.menu_item
|
||||
%span.name{ "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "resend_confirmation" }
|
||||
= t('.resend_confirmation')
|
||||
%div.menu_item
|
||||
%span.name.invoices-modal{'ng-controller' => 'bulkInvoiceCtrl', 'ng-click' => 'createBulkInvoice()' }
|
||||
= t('.print_invoices')
|
||||
%div.menu_item
|
||||
%span.name{'ng-controller' => 'bulkCancelCtrl', 'ng-click' => 'cancelSelectedOrders()' }
|
||||
= t('.cancel_orders')
|
||||
|
||||
|
||||
= render partial: 'per_page_controls', locals: { position: "right" }
|
||||
|
||||
@@ -63,7 +65,7 @@
|
||||
%tbody
|
||||
%tr{ng: {repeat: 'order in orders track by order.id', class: {even: "'even'", odd: "'odd'"}}, 'ng-class' => "{'state-{{order.state}}': true, 'row-loading': rowStatus[order.id] == 'loading'}"}
|
||||
%td.align-center
|
||||
%input{type: 'checkbox', 'ng-model' => 'checkboxes[order.id]', 'ng-change' => 'toggleSelection(order.id)'}
|
||||
%input{type: 'checkbox', 'ng-model' => 'checkboxes[order.id]', 'ng-change' => 'toggleSelection(order.id)', value: '{{order.id}}', name: 'order_ids[]'}
|
||||
%td.align-center
|
||||
{{order.distributor_name}}
|
||||
%td.align-center
|
||||
@@ -118,3 +120,7 @@
|
||||
= t('.no_orders_found')
|
||||
|
||||
= render 'spree/admin/shared/custom-confirm'
|
||||
|
||||
= render ConfirmModalComponent.new(id: "resend_confirmation", confirm_actions: "click->resend-confirmation-email#confirm", controllers: "resend-confirmation-email") do
|
||||
.margin-bottom-30
|
||||
= t('.resend_confirmation_confirm_html')
|
||||
|
||||
@@ -15,5 +15,6 @@
|
||||
%td.align-center
|
||||
%span{class: "state #{payment.state}"}= t(payment.state, scope: "spree.payment_states", default: payment.state.capitalize)
|
||||
%td.actions
|
||||
- payment.actions.each do |action|
|
||||
= link_to_with_icon "icon-#{action}", Spree.t(action), fire_admin_order_payment_path(@order, payment, e: action), method: :put, no_text: true, data: {action: action, disable_with: ""}
|
||||
.flex
|
||||
- payment.actions.each do |action|
|
||||
= link_to_with_icon "icon-#{action}", Spree.t(action), fire_admin_order_payment_path(@order, payment, e: action), method: :put, no_text: true, data: {action: action, disable_with: ""}
|
||||
|
||||
@@ -45,12 +45,12 @@
|
||||
|
||||
= f.field_container :shipping_categories do
|
||||
= f.label :shipping_category_id, t(:shipping_categories)
|
||||
= f.collection_select(:shipping_category_id, @shipping_categories, :id, :name, { :include_blank => 'None' }, { :class => 'select2' })
|
||||
= f.collection_select(:shipping_category_id, @shipping_categories, :id, :name, { :include_blank => t(:none) }, { :class => 'select2' })
|
||||
= f.error_message_on :shipping_category
|
||||
|
||||
= f.field_container :tax_category do
|
||||
= f.label :tax_category_id, t(:tax_category)
|
||||
= f.collection_select(:tax_category_id, @tax_categories, :id, :name, { :include_blank => 'None' }, { :class => 'select2' })
|
||||
= f.collection_select(:tax_category_id, @tax_categories, :id, :name, { :include_blank => t(:none) }, { :class => 'select2' })
|
||||
= f.error_message_on :tax_category
|
||||
|
||||
.clear
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
= f.field_container :primary_taxon do
|
||||
= f.label :primary_taxon_id, t('.product_category')
|
||||
= f.label :primary_taxon, t('.product_category')
|
||||
%span.required *
|
||||
%br
|
||||
= f.collection_select(:primary_taxon_id, Spree::Taxon.order(:name), :id, :name, {:include_blank => true}, {:class => "select2 fullwidth"})
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
.sixteen.columns.alpha
|
||||
.eight.columns.alpha
|
||||
= f.field_container :supplier do
|
||||
= f.label :supplier_id, t(".supplier")
|
||||
= f.select :supplier_id, options_from_collection_for_select(@producers, :id, :name, @product.supplier_id), {}, { "data-controller": "tom-select", class: "primary" }
|
||||
= f.label :supplier, t(".supplier")
|
||||
%span.required *
|
||||
= f.select :supplier_id, options_from_collection_for_select(@producers, :id, :name, @product.supplier_id), { include_blank: t("spree.admin.products.new.supplier_select_placeholder") }, { "data-controller": "tom-select", class: "primary" }
|
||||
= f.error_message_on :supplier
|
||||
.eight.columns.omega
|
||||
= f.field_container :name do
|
||||
@@ -22,7 +23,7 @@
|
||||
.sixteen.columns.alpha
|
||||
.eight.columns.alpha
|
||||
= f.field_container :variant_unit do
|
||||
= f.label :variant_unit_with_scale, t(".units")
|
||||
= f.label :variant_unit, t(".units")
|
||||
%span.required *
|
||||
%select{id: 'product_variant_unit_with_scale', 'ng-model' => 'product.variant_unit_with_scale', 'ng-options' => 'unit[1] as unit[0] for unit in variant_unit_options', "data-controller": "tom-select","data-tom-select-options-value": '{"allowEmptyOption":false}', class: "primary"}
|
||||
%option{'value' => '', 'ng-hide' => "hasUnit(product)"}
|
||||
@@ -31,9 +32,9 @@
|
||||
= f.error_message_on :variant_unit
|
||||
.two.columns
|
||||
= f.field_container :unit_value do
|
||||
= f.label :unit_value_with_description, t(".value"), 'ng-disabled' => "!hasUnit(product)"
|
||||
= f.label :unit_value, t(".value"), 'ng-disabled' => "!hasUnit(product)"
|
||||
%span.required *
|
||||
%input.fullwidth{ id: 'product_unit_value_with_description', 'ng-model' => 'product.master.unit_value_with_description', :type => 'text', placeholder: "eg. 2", 'ng-disabled' => "!hasUnit(product)" }
|
||||
%input.fullwidth{ id: 'product_unit_value', 'ng-model' => 'product.master.unit_value_with_description', :type => 'text', placeholder: "eg. 2", 'ng-disabled' => "!hasUnit(product)" }
|
||||
%input{ type: 'hidden', 'ng-value': 'product.master.unit_value', "ng-init": "product.master.unit_value='#{@product.master.unit_value}'", name: 'product[unit_value]' }
|
||||
%input{ type: 'hidden', 'ng-value': 'product.master.unit_description', "ng-init": "product.master.unit_description='#{@product.master.unit_description}'", name: 'product[unit_description]' }
|
||||
= f.error_message_on :unit_value
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
|
||||
%link{:href => "https://fonts.googleapis.com/css?family=Open+Sans:400italic,600italic,400,600,700&subset=latin,cyrillic,greek,vietnamese", :rel => "stylesheet", :type => "text/css"}
|
||||
|
||||
= stylesheet_pack_tag 'admin-styles', media: "screen, print"
|
||||
- if feature?(:admin_style_v2, spree_current_user)
|
||||
= stylesheet_pack_tag 'admin-styles-v2', media: "screen, print"
|
||||
- else
|
||||
= stylesheet_pack_tag 'admin-styles', media: "screen, print"
|
||||
= render "layouts/bugsnag_js"
|
||||
= javascript_include_tag 'admin/all'
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
- if flash[:success]
|
||||
.flash.success= flash[:success]
|
||||
|
||||
= render partial: "shared/flashes"
|
||||
|
||||
= render partial: "spree/layouts/admin/progress_spinner"
|
||||
|
||||
%header#header{"data-hook" => ""}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
.sub-header.show-for-medium-down
|
||||
= render partial: "shopping_shared/order_cycles"
|
||||
|
||||
%fieldset.footer-pad
|
||||
#cart-container
|
||||
- if @order.line_items.empty?
|
||||
%div.row{"data-hook" => "empty_cart"}
|
||||
%p= t(:your_cart_is_empty)
|
||||
|
||||
30
app/webpacker/controllers/floating_label_controller.js
Normal file
30
app/webpacker/controllers/floating_label_controller.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import { Controller } from "stimulus";
|
||||
|
||||
export default class extends Controller {
|
||||
connect() {
|
||||
const input = this.element.querySelector("input");
|
||||
input.addEventListener("focus", this.focus.bind(this));
|
||||
input.addEventListener("blur", this.blur.bind(this));
|
||||
if (input.value.length > 0) {
|
||||
this.focus();
|
||||
}
|
||||
|
||||
const label = this.element.querySelector("label");
|
||||
// Add transition class to the label and display the label
|
||||
// after a short delay to avoid flickering
|
||||
setTimeout(() => {
|
||||
label.classList.add("with-transition");
|
||||
label.style.display = "block";
|
||||
}, 100);
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.element.classList.add("active");
|
||||
}
|
||||
|
||||
blur(e) {
|
||||
if (e.target.value.length === 0) {
|
||||
this.element.classList.remove("active");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +1,10 @@
|
||||
import { Controller } from "stimulus";
|
||||
import { useOpenAndCloseAsAModal } from "./mixins/useOpenAndCloseAsAModal";
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["background", "modal"];
|
||||
|
||||
open() {
|
||||
this.backgroundTarget.style.display = "block";
|
||||
this.modalTarget.style.display = "block";
|
||||
|
||||
setTimeout(() => {
|
||||
this.modalTarget.classList.add("in");
|
||||
this.backgroundTarget.classList.add("in");
|
||||
document.querySelector("body").classList.add("modal-open");
|
||||
});
|
||||
}
|
||||
|
||||
close() {
|
||||
this.modalTarget.classList.remove("in");
|
||||
this.backgroundTarget.classList.remove("in");
|
||||
document.querySelector("body").classList.remove("modal-open");
|
||||
|
||||
setTimeout(() => {
|
||||
this.backgroundTarget.style.display = "none";
|
||||
this.modalTarget.style.display = "none";
|
||||
}, 200);
|
||||
}
|
||||
|
||||
closeIfEscapeKey(e) {
|
||||
if (e.code == "Escape") {
|
||||
this.close();
|
||||
}
|
||||
connect() {
|
||||
useOpenAndCloseAsAModal(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
import { Controller } from "stimulus";
|
||||
import ModalLinkController from "./modal_link_controller";
|
||||
|
||||
export default class extends Controller {
|
||||
static values = { target: String };
|
||||
|
||||
open() {
|
||||
let helpModal = document.getElementById(this.targetValue);
|
||||
let helpModalController =
|
||||
this.application.getControllerForElementAndIdentifier(
|
||||
helpModal,
|
||||
"help-modal"
|
||||
);
|
||||
helpModalController.open();
|
||||
export default class extends ModalLinkController {
|
||||
getIdentifier() {
|
||||
return "help-modal";
|
||||
}
|
||||
}
|
||||
|
||||
31
app/webpacker/controllers/mixins/useOpenAndCloseAsAModal.js
Normal file
31
app/webpacker/controllers/mixins/useOpenAndCloseAsAModal.js
Normal file
@@ -0,0 +1,31 @@
|
||||
export const useOpenAndCloseAsAModal = (controller) => {
|
||||
Object.assign(controller, {
|
||||
open: function () {
|
||||
this.backgroundTarget.style.display = "block";
|
||||
this.modalTarget.style.display = "block";
|
||||
|
||||
setTimeout(() => {
|
||||
this.modalTarget.classList.add("in");
|
||||
this.backgroundTarget.classList.add("in");
|
||||
document.querySelector("body").classList.add("modal-open");
|
||||
});
|
||||
}.bind(controller),
|
||||
|
||||
close: function () {
|
||||
this.modalTarget.classList.remove("in");
|
||||
this.backgroundTarget.classList.remove("in");
|
||||
document.querySelector("body").classList.remove("modal-open");
|
||||
|
||||
setTimeout(() => {
|
||||
this.backgroundTarget.style.display = "none";
|
||||
this.modalTarget.style.display = "none";
|
||||
}, 200);
|
||||
}.bind(controller),
|
||||
|
||||
closeIfEscapeKey: function (e) {
|
||||
if (e.code == "Escape") {
|
||||
this.close();
|
||||
}
|
||||
}.bind(controller),
|
||||
});
|
||||
};
|
||||
15
app/webpacker/controllers/modal_controller.js
Normal file
15
app/webpacker/controllers/modal_controller.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Controller } from "stimulus";
|
||||
import { useOpenAndCloseAsAModal } from "./mixins/useOpenAndCloseAsAModal";
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["background", "modal"];
|
||||
|
||||
connect() {
|
||||
useOpenAndCloseAsAModal(this);
|
||||
window.addEventListener("modal:close", this.close.bind(this));
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
window.removeEventListener("modal:close", this.close);
|
||||
}
|
||||
}
|
||||
18
app/webpacker/controllers/modal_link_controller.js
Normal file
18
app/webpacker/controllers/modal_link_controller.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Controller } from "stimulus";
|
||||
|
||||
export default class extends Controller {
|
||||
static values = { target: String };
|
||||
|
||||
open() {
|
||||
let modal = document.getElementById(this.targetValue);
|
||||
let modalController = this.application.getControllerForElementAndIdentifier(
|
||||
modal,
|
||||
this.getIdentifier()
|
||||
);
|
||||
modalController.open();
|
||||
}
|
||||
|
||||
getIdentifier() {
|
||||
return "modal";
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,9 @@ export default class extends Controller {
|
||||
const stripeCardSelector =
|
||||
this.application.getControllerForElementAndIdentifier(
|
||||
document
|
||||
.getElementById(event.target.dataset.paymentmethodId)
|
||||
.querySelector(
|
||||
`[data-paymentmethod-id="${event.target.dataset.paymentmethodId}"]`
|
||||
)
|
||||
.querySelector('[data-controller="stripe-cards"]'),
|
||||
"stripe-cards"
|
||||
);
|
||||
@@ -27,7 +29,8 @@ export default class extends Controller {
|
||||
Array.from(
|
||||
document.getElementsByClassName("paymentmethod-container")
|
||||
).forEach((container) => {
|
||||
const enabled = container.id === paymentMethodContainerId;
|
||||
const enabled =
|
||||
container.dataset.paymentmethodId === paymentMethodContainerId;
|
||||
|
||||
if (enabled) {
|
||||
container.style.display = "block";
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import ApplicationController from "./application_controller";
|
||||
|
||||
export default class extends ApplicationController {
|
||||
connect() {
|
||||
super.connect();
|
||||
}
|
||||
|
||||
confirm() {
|
||||
const order_ids = [];
|
||||
document
|
||||
.querySelectorAll("#listing_orders input[name='order_ids[]']:checked")
|
||||
.forEach((checkbox) => {
|
||||
order_ids.push(checkbox.value);
|
||||
});
|
||||
|
||||
this.stimulate("ResendConfirmationEmailReflex#confirm", order_ids);
|
||||
}
|
||||
}
|
||||
@@ -2,27 +2,24 @@ import { Controller } from "stimulus";
|
||||
export default class extends Controller {
|
||||
static targets = [
|
||||
"shippingMethodDescription",
|
||||
"shippingMethodDescriptionContent",
|
||||
"shippingMethodAddress",
|
||||
"shippingAddressCheckbox",
|
||||
];
|
||||
connect() {
|
||||
// Hide shippingMethodDescription by default
|
||||
}
|
||||
connect() {}
|
||||
|
||||
selectShippingMethod(event) {
|
||||
const input = event.target;
|
||||
if (input.tagName === "INPUT") {
|
||||
// Shipping method description
|
||||
if (input.dataset.description.length > 0) {
|
||||
this.shippingMethodDescriptionTarget.style.display = "block";
|
||||
this.shippingMethodDescriptionContentTarget.innerText =
|
||||
input.dataset.description;
|
||||
} else {
|
||||
this.shippingMethodDescriptionTarget.style.display = "none";
|
||||
this.shippingMethodDescriptionContentTarget.innerText = null;
|
||||
}
|
||||
// Require a ship address
|
||||
// -- Shipping method description
|
||||
// Hide all shipping method descriptions
|
||||
this.shippingMethodDescriptionTargets.forEach((t) => {
|
||||
t.style.display = "none";
|
||||
});
|
||||
// but not the one we want ie. the one that matches the shipping method id
|
||||
this.shippingMethodDescriptionTargets.find(
|
||||
(e) => e.dataset["shippingmethodid"] == input.value
|
||||
).style.display = "block";
|
||||
// -- Require a ship address
|
||||
if (
|
||||
input.dataset.requireaddress === "true" &&
|
||||
!this.shippingAddressCheckboxTarget.checked
|
||||
|
||||
@@ -127,5 +127,4 @@
|
||||
@import "app/components/pagination_component/pagination_component";
|
||||
@import "app/components/table_header_component/table_header_component";
|
||||
@import "app/components/search_input_component/search_input_component";
|
||||
|
||||
@import "v2/main.scss";
|
||||
@import 'app/components/confirm_modal_component/confirm_modal_component';
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
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) }
|
||||
|
||||
16
app/webpacker/css/admin/globals/palette.scss
Normal file
16
app/webpacker/css/admin/globals/palette.scss
Normal file
@@ -0,0 +1,16 @@
|
||||
// Basic color palette for admin
|
||||
$color-1: #FFFFFF !default; // White
|
||||
$color-2: #9FC820 !default; // Green
|
||||
$color-3: #5498DA !default; // Light Blue
|
||||
$color-4: #6788A2 !default; // Dark Blue
|
||||
$color-5: #C60F13 !default; // Red
|
||||
$color-6: #FF9300 !default; // Yellow
|
||||
|
||||
@mixin basicColorPalette($color1, $color2, $color3, $color4, $color5, $color6) {
|
||||
$color-1: $color1 !global;
|
||||
$color-2: $color2 !global;
|
||||
$color-3: $color3 !global;
|
||||
$color-4: $color4 !global;
|
||||
$color-5: $color5 !global;
|
||||
$color-6: $color6 !global;
|
||||
}
|
||||
@@ -9,14 +9,6 @@ $base-font-family: "Open Sans", "Helvetica Neue", "Helvetica", Helvetica, Arial,
|
||||
// Colors
|
||||
//--------------------------------------------------------------
|
||||
|
||||
// Basic color palette for admin
|
||||
$color-1: #FFFFFF !default; // White
|
||||
$color-2: #9FC820 !default; // Green
|
||||
$color-3: #5498DA !default; // Light Blue
|
||||
$color-4: #6788A2 !default; // Dark Blue
|
||||
$color-5: #C60F13 !default; // Red
|
||||
$color-6: #FF9300 !default; // Yellow
|
||||
|
||||
// Body base colors
|
||||
$color-body-bg: $color-1 !default;
|
||||
$color-body-text: $color-4 !default;
|
||||
|
||||
@@ -11,27 +11,41 @@ select[type="submit"],
|
||||
input[type="button"],
|
||||
select[type="button"],
|
||||
.select2-container-multi [type="button"].select2-choices,
|
||||
button,
|
||||
button:not(.no-text),
|
||||
.button,
|
||||
.actions a:not([class*="icon-"]),
|
||||
.actions a:not(.no-text),
|
||||
fieldset .filter-actions button, // Be more specific to be sure to override the form button style (with a white border)
|
||||
fieldset .filter-actions .button:hover,
|
||||
.admin__section-header .ofn-drop-down // Same behavior as the button
|
||||
{
|
||||
&.disabled,
|
||||
&[disabled] {
|
||||
@include backgroundAndBorder($v2-light-grey);
|
||||
@include backgroundAndBorder($v2-blue-light);
|
||||
|
||||
&:hover {
|
||||
@include backgroundAndBorder($v2-blue);
|
||||
box-shadow: $v2-box-shadow;
|
||||
}
|
||||
|
||||
&:not(.disabled):not([disabled]):not(.secondary) {
|
||||
// Change the color of the button only if it's not disabled
|
||||
@include backgroundAndBorder($v2-blue-light);
|
||||
&.disabled,
|
||||
&[disabled],
|
||||
&.disabled.secondary,
|
||||
&[disabled].secondary {
|
||||
@include backgroundAndBorder($v2-dark-light-grey);
|
||||
box-shadow: none;
|
||||
cursor: default;
|
||||
color: white;
|
||||
|
||||
&:hover {
|
||||
@include backgroundAndBorder($v2-blue);
|
||||
box-shadow: $v2-box-shadow;
|
||||
@include backgroundAndBorder($v2-dark-light-grey);
|
||||
box-shadow: none;
|
||||
cursor: default;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
&.secondary {
|
||||
&.secondary,
|
||||
&.cancel,
|
||||
&.icon-remove,
|
||||
&#clear_all_filters {
|
||||
background-color: $white;
|
||||
border: 2px solid $v2-blue-light;
|
||||
color: $v2-blue-light;
|
||||
@@ -60,7 +74,6 @@ button,
|
||||
}
|
||||
}
|
||||
|
||||
#table-filter fieldset:has(.actions) {
|
||||
// do not apply border to filter actions as it's drawn by the #table-filter .actions before and after pseudo elements
|
||||
#table-filter fieldset {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
9
app/webpacker/css/admin/v2/components/dropdown.scss
Normal file
9
app/webpacker/css/admin/v2/components/dropdown.scss
Normal file
@@ -0,0 +1,9 @@
|
||||
/* Override app/webpacker/css/admin/dropdown.scss */
|
||||
|
||||
.ofn-drop-down,
|
||||
.ofn-drop-down-with-prepend .ofn-drop-down-prepend {
|
||||
background-color: white;
|
||||
&.disabled {
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
11
app/webpacker/css/admin/v2/components/sidebar.scss
Normal file
11
app/webpacker/css/admin/v2/components/sidebar.scss
Normal file
@@ -0,0 +1,11 @@
|
||||
/* Override file app/webpacker/css/admin/components/sidebar.scss */
|
||||
|
||||
#sidebar {
|
||||
border-color: #e7e7e7;
|
||||
.sidebar-title {
|
||||
color: $v2-blue;
|
||||
& > span {
|
||||
background-color: $v2-body-bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,17 @@
|
||||
/* Overide tables.scss app/webpacker/css/admin/components/tables.scss */
|
||||
|
||||
table {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
table thead tr:first-child th:first-child {
|
||||
border-top-left-radius: 3px;
|
||||
}
|
||||
|
||||
table thead tr:first-child th:last-child,
|
||||
table thead th.force-rounded-right {
|
||||
border-top-right-radius: 3px;
|
||||
}
|
||||
table thead th {
|
||||
background-color: $v2-medium-light-grey;
|
||||
border: none;
|
||||
@@ -13,28 +25,31 @@ table thead th {
|
||||
}
|
||||
}
|
||||
|
||||
table tr:not([class*="state"]) {
|
||||
th:first-child,
|
||||
td:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
}
|
||||
|
||||
table tbody tr {
|
||||
&:first-child th,
|
||||
&:first-child td {
|
||||
border-top: none; // Don't show the top border of the first row
|
||||
}
|
||||
td:not(:first-child) {
|
||||
border-left: none; // Only show left border on the first cells, as it indicates the order state by its color
|
||||
}
|
||||
|
||||
td {
|
||||
border-bottom: none; // By default, do not show the border of the cells
|
||||
border-right: none;
|
||||
border-top: none;
|
||||
|
||||
border: none;
|
||||
border-bottom: 2px solid $v2-medium-light-grey;
|
||||
&.actions {
|
||||
border-bottom: 2px solid $v2-medium-light-grey !important; // needs to be important because of already defined with important
|
||||
}
|
||||
|
||||
> .flex {
|
||||
display: flex;
|
||||
column-gap: 10px;
|
||||
}
|
||||
|
||||
&.actions > .flex {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
&.even,
|
||||
&.odd {
|
||||
@@ -44,30 +59,91 @@ table tbody tr {
|
||||
}
|
||||
}
|
||||
|
||||
table th.actions,
|
||||
table td.actions {
|
||||
table thead tr th.actions,
|
||||
table tbody tr td.actions {
|
||||
// Special for icons in the actions column
|
||||
[class*="icon-"].no-text {
|
||||
border: 2px solid $v2-blue-light;
|
||||
background-color: $v2-blue-lightest;
|
||||
[class*="icon-"],
|
||||
button[class*="icon-"]:not(.disabled):not([disabled]):not(.secondary):not(.cancel) {
|
||||
color: $v2-blue;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
border-color: $v2-blue;
|
||||
background-color: $v2-blue-light;
|
||||
box-shadow: $v2-box-shadow;
|
||||
&:before {
|
||||
width: auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&:before {
|
||||
color: white;
|
||||
&.no-text {
|
||||
border: 2px solid $v2-blue-light;
|
||||
display: flex; // Be sure that display: flex; is applied
|
||||
padding-top: 0;
|
||||
|
||||
&:hover {
|
||||
border-color: $v2-blue;
|
||||
box-shadow: $v2-box-shadow;
|
||||
|
||||
&:before {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.icon-edit:hover,
|
||||
.icon-capture:hover,
|
||||
.icon-ok:hover,
|
||||
.icon-plus:hover,
|
||||
.icon-road:hover {
|
||||
background-color: $v2-blue;
|
||||
color: $color-1;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
thead th.actions,
|
||||
thead td.actions {
|
||||
background-color: $v2-medium-light-grey !important;
|
||||
}
|
||||
tbody tr td.actions {
|
||||
background-color: white !important;
|
||||
}
|
||||
td {
|
||||
&.actions {
|
||||
padding-left: 20px;
|
||||
border-bottom: 2px solid $v2-medium-light-grey !important; // needs to be important because of already defined with important
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
table#listing_orders td {
|
||||
// When the table is the listing of orders, we need to increase the height of the cells
|
||||
padding: 20px 0;
|
||||
table tbody tr:hover > td {
|
||||
background-color: #e9f3fc !important; // needs to be important because of already defined with important
|
||||
}
|
||||
|
||||
&.actions {
|
||||
padding-left: 20px;
|
||||
table#listing_orders {
|
||||
td {
|
||||
// When the table is the listing of orders, we need to increase the height of the cells
|
||||
padding: 20px 0;
|
||||
|
||||
&:not(:first-child) {
|
||||
border-left: none; // Only show left border on the first cells, as it indicates the order state by its color
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
table#listing_order_cycles tr.open td {
|
||||
background-color: #d9fccb !important; // needs to be important because of already defined with important
|
||||
}
|
||||
table#listing_order_cycles tr.closed td {
|
||||
background-color: #eee !important; // needs to be important because of already defined with important
|
||||
}
|
||||
table#listing_order_cycles tr.upcoming td {
|
||||
background-color: #fbfccb !important; // needs to be important because of already defined with important
|
||||
}
|
||||
|
||||
tbody.panel-ctrl.expanded > tr:not(.panel-row) > td {
|
||||
border-bottom: 1px solid #6788a2 !important; // needs to be important because of already defined with important
|
||||
}
|
||||
|
||||
tbody.panel-ctrl.expanded > tr:not(.panel-row) > td.selected {
|
||||
border-bottom: none !important; // it's a bit annoying to always put that important, but it's the only way to override the default style
|
||||
}
|
||||
|
||||
10
app/webpacker/css/admin/v2/components/tags-input.scss
Normal file
10
app/webpacker/css/admin/v2/components/tags-input.scss
Normal file
@@ -0,0 +1,10 @@
|
||||
tags-input .tags li.tag-item {
|
||||
background-color: $v2-blue-light;
|
||||
}
|
||||
|
||||
tags-input .tags {
|
||||
box-shadow: none;
|
||||
&.focused {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
47
app/webpacker/css/admin/v2/components/tom_select.scss
Normal file
47
app/webpacker/css/admin/v2/components/tom_select.scss
Normal file
@@ -0,0 +1,47 @@
|
||||
/* Override app/webpacker/css/admin/components/tom_select.scss */
|
||||
|
||||
.ts-wrapper.primary.focus .ts-control,
|
||||
.ts-wrapper.primary .ts-control {
|
||||
background-color: white;
|
||||
border: 1px solid $v2-light-grey;
|
||||
color: $v2-medium-grey;
|
||||
|
||||
&:after {
|
||||
border-color: $v2-medium-grey transparent transparent transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.ts-wrapper.dropdown-active.primary .ts-control {
|
||||
background-color: transparent;
|
||||
border-color: $v2-light-grey;
|
||||
color: $v2-medium-grey;
|
||||
|
||||
&:after {
|
||||
border-color: transparent transparent $v2-medium-grey transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.ts-wrapper.dropdown-active.focus .ts-control {
|
||||
border-color: $v2-medium-grey;
|
||||
}
|
||||
|
||||
.dropdown-input-wrap {
|
||||
.dropdown-input {
|
||||
border: 1px solid $v2-light-grey;
|
||||
}
|
||||
}
|
||||
|
||||
.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: $v2-blue;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.ts-dropdown.single {
|
||||
border-color: $v2-medium-grey;
|
||||
}
|
||||
19
app/webpacker/css/admin/v2/components/wizard_progress.scss
Normal file
19
app/webpacker/css/admin/v2/components/wizard_progress.scss
Normal file
@@ -0,0 +1,19 @@
|
||||
ul.wizard-progress li {
|
||||
a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
background-color: $v2-dark-light-grey;
|
||||
&:before,
|
||||
&:after {
|
||||
background-color: $v2-dark-light-grey;
|
||||
}
|
||||
|
||||
&.current {
|
||||
background-color: $v2-blue-light;
|
||||
&:before,
|
||||
&:after {
|
||||
background-color: $v2-blue-light;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,22 @@
|
||||
@import "variables.scss";
|
||||
@import "shared/typography.scss";
|
||||
|
||||
body.admin.admin-v2 {
|
||||
@import "navigation.scss";
|
||||
@import "plugins/select2.scss";
|
||||
@import "plugins/powertip.scss";
|
||||
@import "plugins/flatpickr-customization.scss";
|
||||
@import "shared/forms.scss";
|
||||
@import "components/buttons.scss";
|
||||
@import "components/tables.scss";
|
||||
@import "components/progress.scss";
|
||||
@import "navigation.scss";
|
||||
@import "plugins/select2.scss";
|
||||
@import "plugins/powertip.scss";
|
||||
@import "plugins/flatpickr-customization.scss";
|
||||
@import "shared/forms.scss";
|
||||
@import "components/buttons.scss";
|
||||
@import "components/tables.scss";
|
||||
@import "components/progress.scss";
|
||||
@import "components/sidebar.scss";
|
||||
@import "components/tom_select.scss";
|
||||
@import "components/dropdown.scss";
|
||||
@import "components/wizard_progress.scss";
|
||||
@import "components/tags-input.scss";
|
||||
|
||||
@import "others.scss";
|
||||
|
||||
body {
|
||||
background-color: $v2-body-bg;
|
||||
}
|
||||
|
||||
@@ -60,3 +60,25 @@
|
||||
color: $v2-medium-dark-grey;
|
||||
}
|
||||
}
|
||||
|
||||
nav.menu ul li,
|
||||
nav.menu ul #admin-menu li,
|
||||
#admin-menu nav.menu ul li {
|
||||
&.active {
|
||||
a {
|
||||
color: $v2-blue-dark;
|
||||
border-bottom-color: $v2-blue-dark;
|
||||
}
|
||||
}
|
||||
|
||||
&.selected a,
|
||||
a {
|
||||
&:hover {
|
||||
color: $v2-blue-dark;
|
||||
border-bottom-color: $v2-blue-dark;
|
||||
border-top-color: transparent;
|
||||
border-right-color: transparent;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
6
app/webpacker/css/admin/v2/others.scss
Normal file
6
app/webpacker/css/admin/v2/others.scss
Normal file
@@ -0,0 +1,6 @@
|
||||
/* The aim of this file is to not create a file for each small modification on components */
|
||||
|
||||
#advanced_settings {
|
||||
background-color: $v2-blue-lightest;
|
||||
border-color: $v2-blue-dark;
|
||||
}
|
||||
@@ -28,4 +28,31 @@
|
||||
&.sw:before {
|
||||
border-right-color: $v2-blue;
|
||||
}
|
||||
|
||||
&.edit,
|
||||
&.green,
|
||||
&.capture,
|
||||
&.save,
|
||||
&.add {
|
||||
background-color: $v2-blue;
|
||||
|
||||
&.n:before,
|
||||
&.ne:before,
|
||||
&.nw:before {
|
||||
border-top-color: $v2-blue;
|
||||
}
|
||||
&.e:before,
|
||||
&.nw:before,
|
||||
&.sw:before {
|
||||
border-right-color: $v2-blue;
|
||||
}
|
||||
&.s:before,
|
||||
&.se:before,
|
||||
&.sw:before {
|
||||
border-bottom-color: $v2-blue;
|
||||
}
|
||||
&.w:before {
|
||||
border-left-color: $v2-blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
.select2-container {
|
||||
.select2-choice {
|
||||
background-color: transparent;
|
||||
background-color: white;
|
||||
border: 1px solid $v2-light-grey !important;
|
||||
color: $v2-medium-grey !important;
|
||||
padding-left: 5px;
|
||||
font-size: 13px;
|
||||
padding-top: 3px;
|
||||
height: 35px;
|
||||
|
||||
.select2-arrow {
|
||||
color: $v2-medium-grey;
|
||||
@@ -17,7 +17,7 @@
|
||||
&.select2-container-active,
|
||||
&:hover {
|
||||
.select2-choice {
|
||||
background-color: transparent !important;
|
||||
background-color: white !important;
|
||||
border-color: $v2-medium-grey !important;
|
||||
}
|
||||
}
|
||||
@@ -37,16 +37,34 @@
|
||||
}
|
||||
|
||||
.select2-container-multi {
|
||||
&.select2-dropdown-open,
|
||||
&.select2-container-active {
|
||||
.select2-choices {
|
||||
border-color: $v2-medium-grey !important;
|
||||
}
|
||||
}
|
||||
.select2-choices {
|
||||
border-color: $v2-medium-grey !important;
|
||||
min-height: 35px;
|
||||
.select2-search-choice {
|
||||
background-color: $v2-blue-light;
|
||||
}
|
||||
}
|
||||
&.select2-drop-above {
|
||||
.select2-choices {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-left-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.select2-drop {
|
||||
border-color: $v2-medium-grey;
|
||||
&.select2-drop-above.select2-drop-active {
|
||||
border-color: $v2-medium-grey;
|
||||
}
|
||||
}
|
||||
|
||||
.select2-search {
|
||||
|
||||
@@ -18,18 +18,20 @@ fieldset {
|
||||
// Change the color of all inputs
|
||||
color: $v2-medium-grey;
|
||||
border-color: $v2-light-grey !important;
|
||||
font-size: 13px;
|
||||
|
||||
&:focus {
|
||||
border-color: $v2-medium-grey;
|
||||
border-color: $v2-medium-grey !important;
|
||||
}
|
||||
}
|
||||
|
||||
fieldset label {
|
||||
color: $v2-medium-grey;
|
||||
color: $v2-medium-dark-grey;
|
||||
}
|
||||
|
||||
fieldset legend {
|
||||
color: $v2-blue;
|
||||
background-color: $v2-body-bg;
|
||||
}
|
||||
|
||||
input[type="checkbox"],
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
body.admin.admin-v2 {
|
||||
color: $v2-body-grey;
|
||||
|
||||
a:not(.button) {
|
||||
@include v2-link-color();
|
||||
}
|
||||
a:not(.button) {
|
||||
@include v2-link-color();
|
||||
}
|
||||
|
||||
h4 {
|
||||
color: $v2-medium-dark-grey;
|
||||
}
|
||||
|
||||
@@ -7,8 +7,9 @@ $v2-orange-lightest: #fcdbd4;
|
||||
|
||||
$v2-dark-grey: #333333;
|
||||
$v2-medium-dark-grey: #444444;
|
||||
$v2-body-grey: #666666;
|
||||
$v2-body-grey: $color-4;
|
||||
$v2-medium-grey: #717171;
|
||||
$v2-dark-light-grey: #d9d9d9;
|
||||
$v2-medium-light-grey: #e6e6e6;
|
||||
$v2-light-grey: #e7e7e7;
|
||||
|
||||
@@ -21,3 +22,5 @@ $v2-green: #019854;
|
||||
$v2-green-light: #01cb70;
|
||||
|
||||
$v2-box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); // Default box shadow for actions stuff
|
||||
|
||||
$v2-body-bg: #f7f9fa;
|
||||
|
||||
@@ -161,13 +161,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
// singleLineSelectors directive provides a drop-down that can overlap
|
||||
// content. Ensure that the dropdown appears above the content.
|
||||
.filter-row {
|
||||
position: relative;
|
||||
z-index: 90;
|
||||
}
|
||||
|
||||
.sticky-shop-filters-container {
|
||||
position: sticky;
|
||||
top: $topbar-height;
|
||||
|
||||
@@ -77,3 +77,4 @@ ofn-modal {
|
||||
@import '../admin/shared/scroll_bar';
|
||||
|
||||
@import 'app/components/help_modal_component/help_modal_component';
|
||||
@import 'app/components/confirm_modal_component/confirm_modal_component';
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#cart-container {
|
||||
padding: 25px;
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
|
||||
#update-cart {
|
||||
#errorExplanation {
|
||||
display: none;
|
||||
@@ -6,6 +11,8 @@
|
||||
|
||||
#cart-detail {
|
||||
width: 100%;
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
|
||||
.cart-item-delete,
|
||||
.bought-item-delete {
|
||||
|
||||
@@ -34,13 +34,16 @@
|
||||
|
||||
span, span > a {
|
||||
color: $white;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
&.success {
|
||||
border-bottom: 5px solid $clr-turquoise-bright;
|
||||
|
||||
span {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
span.checkout-tab-label {
|
||||
&:after {
|
||||
content: '✓';
|
||||
@@ -98,7 +101,6 @@
|
||||
font-size: 1.06rem;
|
||||
@include headingFont;
|
||||
font-weight: $font-weight-bold;
|
||||
text-decoration: underline;
|
||||
color: $darker-grey;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
@@ -158,6 +160,18 @@
|
||||
|
||||
label {
|
||||
margin-top: 0.3rem;
|
||||
& + em {
|
||||
margin-left: -0.5rem;
|
||||
font-size: 14px; // same as label
|
||||
font-weight: bold;
|
||||
// Add opening and closing parentheses
|
||||
&:before {
|
||||
content: "(";
|
||||
}
|
||||
&:after {
|
||||
content: ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -240,8 +254,10 @@
|
||||
}
|
||||
|
||||
&.cancel {
|
||||
background-color: $grey-100;
|
||||
color: $black;
|
||||
background-color: $white;
|
||||
border: 1px solid $orange-500;
|
||||
color: $orange-500;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,3 +322,62 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#line-items {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.two-columns-inputs {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
justify-content: space-between;
|
||||
|
||||
> .checkout-input {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&:last-child > .checkout-input {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 700px) {
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
&:last-child > .checkout-input {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shows label as a placeholder, inside the input and when the input is focused shows the label above the input
|
||||
.checkout-input.with-floating-label {
|
||||
position: relative;
|
||||
|
||||
label {
|
||||
display: none; // Display none by default, and shown by floating_label_controller
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
font-size: 0.875rem;
|
||||
padding: 8px;
|
||||
padding-left: 9px;
|
||||
color: $min-accessible-grey;
|
||||
pointer-events: none;
|
||||
transform: translateY(0);
|
||||
transform-origin: top left;
|
||||
&.with-transition {
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
}
|
||||
&.active {
|
||||
label {
|
||||
transform: translateY(-9px) translateX(10px) scale(0.9);
|
||||
background-color: white;
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
6
app/webpacker/packs/admin-styles-v2.scss
Normal file
6
app/webpacker/packs/admin-styles-v2.scss
Normal file
@@ -0,0 +1,6 @@
|
||||
@import '../css/admin/globals/palette';
|
||||
@include basicColorPalette(#FFFFFF, #69A95D, #14B6CC, #484848, #C1122B, #F27052);
|
||||
|
||||
@import "../css/admin/all.scss";
|
||||
|
||||
@import "../css/admin/v2/main.scss";
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user