mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-13 18:46:49 +00:00
Compare commits
346 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e876a25d59 | ||
|
|
2a780151be | ||
|
|
9d2009d2af | ||
|
|
f887533dda | ||
|
|
bef3f154d6 | ||
|
|
6fb775d5ed | ||
|
|
b5a8563725 | ||
|
|
1a9ade6de9 | ||
|
|
48df853ff5 | ||
|
|
2137a2addb | ||
|
|
e6a7239716 | ||
|
|
25bed92f2e | ||
|
|
909cd407dd | ||
|
|
f2d25748b1 | ||
|
|
6396e6e970 | ||
|
|
e52f813dae | ||
|
|
9ab2eec30c | ||
|
|
f96b37dae3 | ||
|
|
5b68b2f707 | ||
|
|
ff634bd870 | ||
|
|
5e68604f11 | ||
|
|
c4edd3a683 | ||
|
|
574781e901 | ||
|
|
8ea4f933da | ||
|
|
1e9820f291 | ||
|
|
34ed86cf2d | ||
|
|
706168f2f0 | ||
|
|
3ecb5c0c75 | ||
|
|
249a3c4e18 | ||
|
|
2b8ebba233 | ||
|
|
758394464b | ||
|
|
d3c624ae10 | ||
|
|
163c65849e | ||
|
|
99ff714913 | ||
|
|
c2f302450f | ||
|
|
9186bcd455 | ||
|
|
3d074b530f | ||
|
|
20783db373 | ||
|
|
d5b37a5171 | ||
|
|
3efe2f878d | ||
|
|
064fee79b3 | ||
|
|
d13f182801 | ||
|
|
ee34935223 | ||
|
|
0b7ce0d6db | ||
|
|
9dd02044a5 | ||
|
|
d8a7190f43 | ||
|
|
e5e0fcc887 | ||
|
|
53496ff9eb | ||
|
|
6635a89af7 | ||
|
|
c1248857b8 | ||
|
|
8c95399292 | ||
|
|
14c1abb861 | ||
|
|
e2d61f5e89 | ||
|
|
5a1ef04c67 | ||
|
|
e9e73ef0e4 | ||
|
|
be844253eb | ||
|
|
001e3688da | ||
|
|
b4ffd4dcc2 | ||
|
|
e5a9606449 | ||
|
|
9eabbb8dab | ||
|
|
1217811402 | ||
|
|
d4f2fcb98a | ||
|
|
0b2417849c | ||
|
|
3e8369c8f5 | ||
|
|
cbaedcec92 | ||
|
|
bf2c1a0c1d | ||
|
|
0284eebf35 | ||
|
|
e4ba515109 | ||
|
|
af1f6f6c6d | ||
|
|
b0e8ee42c1 | ||
|
|
86aeb6a3c7 | ||
|
|
5d83414e9b | ||
|
|
9820d7de38 | ||
|
|
910eca810a | ||
|
|
6feaddf747 | ||
|
|
10f6fb91f6 | ||
|
|
c7bd4b94b8 | ||
|
|
dd223a21f2 | ||
|
|
549366ff15 | ||
|
|
e92f60fb1c | ||
|
|
92b05c76a3 | ||
|
|
fa6fa0be64 | ||
|
|
752efac7cf | ||
|
|
2b1f1f748b | ||
|
|
798cd9e778 | ||
|
|
2f5b0a5afb | ||
|
|
de2d4a5870 | ||
|
|
b3728568a8 | ||
|
|
6ba98b4b2c | ||
|
|
d3d6921a0f | ||
|
|
68393f1444 | ||
|
|
229e6fa0a3 | ||
|
|
8a069787d1 | ||
|
|
29ed38a6cc | ||
|
|
4c7d3a491a | ||
|
|
b0f90cf43c | ||
|
|
02ec0634b3 | ||
|
|
64d21969f0 | ||
|
|
0995adeb59 | ||
|
|
073a3fe2b4 | ||
|
|
c07df6a5a6 | ||
|
|
a7d109833d | ||
|
|
0364a14073 | ||
|
|
ddc8d33356 | ||
|
|
cd81dfaead | ||
|
|
25073ada84 | ||
|
|
15b6f9dd5e | ||
|
|
0377e02dc1 | ||
|
|
f679708a4e | ||
|
|
0f748a3333 | ||
|
|
bdedaa06d8 | ||
|
|
6a41d9be87 | ||
|
|
3616a27566 | ||
|
|
60bdde6349 | ||
|
|
5faf33fabe | ||
|
|
f3b1a5dd35 | ||
|
|
5ae61017f5 | ||
|
|
61dffb8821 | ||
|
|
07ccbf7f98 | ||
|
|
f9fabd088c | ||
|
|
a3af6617a9 | ||
|
|
9f7fb654c8 | ||
|
|
b4a6686eac | ||
|
|
ac13ff114c | ||
|
|
af9187947f | ||
|
|
f0fdbf7cf4 | ||
|
|
74ab31c0e6 | ||
|
|
9400516b56 | ||
|
|
6ebfb02d0e | ||
|
|
75c7e0b939 | ||
|
|
62eb2bba13 | ||
|
|
3fa9e857a8 | ||
|
|
11a77043eb | ||
|
|
58b43c7bc9 | ||
|
|
7da10db055 | ||
|
|
be41271038 | ||
|
|
04e13e1136 | ||
|
|
8868b7eb12 | ||
|
|
c85d00fcb8 | ||
|
|
2c6dab9c85 | ||
|
|
7b2a146404 | ||
|
|
c45194473b | ||
|
|
3c0e6eeee2 | ||
|
|
ca5a5bf301 | ||
|
|
ddf68444fb | ||
|
|
4867649fc9 | ||
|
|
35841066d1 | ||
|
|
9bc81f236c | ||
|
|
e26a54d897 | ||
|
|
ed1d637eb5 | ||
|
|
831284c5c8 | ||
|
|
e45b8f6981 | ||
|
|
d0f8f985fb | ||
|
|
33eec61af8 | ||
|
|
00c324ae45 | ||
|
|
12a016d31d | ||
|
|
8c7a7348f4 | ||
|
|
af50bde088 | ||
|
|
340b92e580 | ||
|
|
f64653db14 | ||
|
|
e6ef661f0d | ||
|
|
3c2b6f4ed1 | ||
|
|
ec6f6056a8 | ||
|
|
6a621f47aa | ||
|
|
dae23d3c3b | ||
|
|
aae5ae9f1e | ||
|
|
888e0e0bb4 | ||
|
|
a0b0fb05a6 | ||
|
|
a11562e4dd | ||
|
|
986837d601 | ||
|
|
def2693afc | ||
|
|
55f26f0a3d | ||
|
|
7245d1eff4 | ||
|
|
353d6fbc5f | ||
|
|
87ef0215b8 | ||
|
|
4b6a02cb92 | ||
|
|
196a301133 | ||
|
|
b9b8bc70dd | ||
|
|
d42da8737e | ||
|
|
6419edcb1f | ||
|
|
fca82375e8 | ||
|
|
ca0f746cf1 | ||
|
|
a93cf46f50 | ||
|
|
ffb8edef0b | ||
|
|
74a030f6db | ||
|
|
7a8b5e89be | ||
|
|
90690cd238 | ||
|
|
90c621ac07 | ||
|
|
2d5eccbf97 | ||
|
|
7e6259da31 | ||
|
|
1f75c7e5e4 | ||
|
|
a1e6e4c38f | ||
|
|
77fb73f802 | ||
|
|
9f7376a5ae | ||
|
|
5739a82c19 | ||
|
|
eae373ef4b | ||
|
|
465332d5f9 | ||
|
|
e98b89625f | ||
|
|
cf61254c9e | ||
|
|
1d92d6cc33 | ||
|
|
6b32764c99 | ||
|
|
be4fbc4d23 | ||
|
|
ea72a10b9a | ||
|
|
9b567a6710 | ||
|
|
a8ce31fa90 | ||
|
|
4c964fea0d | ||
|
|
6d7c41c04b | ||
|
|
a6a695660f | ||
|
|
0058ef5e04 | ||
|
|
4831bae9cb | ||
|
|
f7679780de | ||
|
|
f2ac354e00 | ||
|
|
88ffa46ce7 | ||
|
|
869431c68d | ||
|
|
3d6fd10e59 | ||
|
|
81482683cf | ||
|
|
57f1742f24 | ||
|
|
a1f8530489 | ||
|
|
a75a0da981 | ||
|
|
5744240f91 | ||
|
|
873c56a642 | ||
|
|
f53a75660f | ||
|
|
50dcbe0b57 | ||
|
|
f9861fee79 | ||
|
|
d8ae97f923 | ||
|
|
9f5db217fe | ||
|
|
c1c5dcac09 | ||
|
|
6064f096a7 | ||
|
|
a62fa755f5 | ||
|
|
fa25991f0f | ||
|
|
6f2be1dfa6 | ||
|
|
c81a9fd032 | ||
|
|
665d0cc86b | ||
|
|
a34d8a3f20 | ||
|
|
6e35701dd6 | ||
|
|
9991458d2a | ||
|
|
a843fd73b7 | ||
|
|
9765b1e908 | ||
|
|
5ccadc1f7d | ||
|
|
539805e2c2 | ||
|
|
fac64ef5bf | ||
|
|
a17a0a62bc | ||
|
|
1e91de106f | ||
|
|
73252132a6 | ||
|
|
e3c383c61c | ||
|
|
aafb134be7 | ||
|
|
70a1996435 | ||
|
|
1712cb2617 | ||
|
|
25df057d05 | ||
|
|
24a9991162 | ||
|
|
156ff2da89 | ||
|
|
e36b4ed01a | ||
|
|
41b775b173 | ||
|
|
35570feba0 | ||
|
|
1d8cfe59a2 | ||
|
|
abd3efe82a | ||
|
|
389b53cb71 | ||
|
|
4f60273198 | ||
|
|
856fa8685a | ||
|
|
9ac4c0ba30 | ||
|
|
2709f237f5 | ||
|
|
9db4edcd0d | ||
|
|
22c9f33f4c | ||
|
|
24ea2a4398 | ||
|
|
8178f5388c | ||
|
|
c0c5e9d7dd | ||
|
|
19f8f5c6fa | ||
|
|
83a306c31b | ||
|
|
d6020cdb6f | ||
|
|
3b467dbae8 | ||
|
|
306390440a | ||
|
|
267131626e | ||
|
|
f843a0b4d9 | ||
|
|
965a274332 | ||
|
|
cb2a842746 | ||
|
|
a6655623d0 | ||
|
|
2a2d05ad39 | ||
|
|
e8127d81dc | ||
|
|
cd7906a57b | ||
|
|
02c573f146 | ||
|
|
112017a158 | ||
|
|
4a07d67037 | ||
|
|
54156dfd32 | ||
|
|
ee20d35487 | ||
|
|
be18244abc | ||
|
|
02099ebdae | ||
|
|
d153e58933 | ||
|
|
c2a59a374c | ||
|
|
2a1011921b | ||
|
|
df27ee0d3e | ||
|
|
c2851015ce | ||
|
|
d0c246c345 | ||
|
|
e58546a412 | ||
|
|
6aed9ba549 | ||
|
|
4f2bc33ec3 | ||
|
|
0f3404ca27 | ||
|
|
9e2e460ac5 | ||
|
|
18006ea9c8 | ||
|
|
71b648e9fa | ||
|
|
eacd76bfa4 | ||
|
|
791ff842aa | ||
|
|
ac0123734a | ||
|
|
7cab99efdf | ||
|
|
5378bb7b34 | ||
|
|
942824cd74 | ||
|
|
86accc227e | ||
|
|
1681e8a572 | ||
|
|
e897eb0439 | ||
|
|
36e3362fc1 | ||
|
|
10e123a9c4 | ||
|
|
0101dcdd93 | ||
|
|
9416f61fb3 | ||
|
|
8efd69c3d1 | ||
|
|
dcbdfbb081 | ||
|
|
92968c5efe | ||
|
|
c8ac64566f | ||
|
|
05a72be273 | ||
|
|
b1cd950051 | ||
|
|
f557996817 | ||
|
|
1a64a737d4 | ||
|
|
7c0087cb30 | ||
|
|
17448699f9 | ||
|
|
a413f22e12 | ||
|
|
893952f46b | ||
|
|
061e3cd722 | ||
|
|
a83790951d | ||
|
|
4e33529845 | ||
|
|
a2a8b330b7 | ||
|
|
9669016573 | ||
|
|
2755cb9ec7 | ||
|
|
fdcc4c2447 | ||
|
|
fc0ffda8ec | ||
|
|
a5b5e5de32 | ||
|
|
ef61310bad | ||
|
|
dee1c3d139 | ||
|
|
bb9c54a445 | ||
|
|
e5f396f975 | ||
|
|
a57a93d414 | ||
|
|
a82b1d8129 | ||
|
|
5184fa540c | ||
|
|
356e00bfbb | ||
|
|
5534109122 | ||
|
|
ac8790ecb3 | ||
|
|
d8ece7cd8b | ||
|
|
ee65d70eec | ||
|
|
bf8a31abda |
@@ -49,7 +49,6 @@ Metrics/LineLength:
|
||||
- app/controllers/spree/admin/orders_controller_decorator.rb
|
||||
- app/controllers/spree/admin/payments_controller_decorator.rb
|
||||
- app/controllers/spree/admin/payment_methods_controller_decorator.rb
|
||||
- app/controllers/spree/admin/products_controller_decorator.rb
|
||||
- app/controllers/spree/admin/reports_controller_decorator.rb
|
||||
- app/controllers/spree/api/products_controller_decorator.rb
|
||||
- app/controllers/spree/credit_cards_controller.rb
|
||||
@@ -123,14 +122,11 @@ Metrics/LineLength:
|
||||
- app/serializers/api/admin/subscription_serializer.rb
|
||||
- app/serializers/api/admin/tag_rule_serializer.rb
|
||||
- app/serializers/api/admin/variant_override_serializer.rb
|
||||
- app/serializers/api/admin/variant_serializer.rb
|
||||
- app/services/cart_service.rb
|
||||
- app/services/default_stock_location.rb
|
||||
- app/services/embedded_page_service.rb
|
||||
- app/services/line_item_syncer.rb
|
||||
- app/services/order_cycle_form.rb
|
||||
- app/services/order_factory.rb
|
||||
- app/services/order_syncer.rb
|
||||
- app/services/subscriptions_count.rb
|
||||
- app/services/variants_stock_levels.rb
|
||||
- app/views/json/_groups.rabl
|
||||
@@ -151,15 +147,12 @@ Metrics/LineLength:
|
||||
- lib/open_food_network/order_and_distributor_report.rb
|
||||
- lib/open_food_network/order_cycle_form_applicator.rb
|
||||
- lib/open_food_network/order_cycle_management_report.rb
|
||||
- lib/open_food_network/order_cycle_permissions.rb
|
||||
- lib/open_food_network/order_grouper.rb
|
||||
- lib/open_food_network/orders_and_fulfillments_report.rb
|
||||
- lib/open_food_network/payments_report.rb
|
||||
- lib/open_food_network/permalink_generator.rb
|
||||
- lib/open_food_network/permissions.rb
|
||||
- lib/open_food_network/products_cache.rb
|
||||
- lib/open_food_network/products_renderer.rb
|
||||
- lib/open_food_network/proxy_order_syncer.rb
|
||||
- lib/open_food_network/reports/bulk_coop_allocation_report.rb
|
||||
- lib/open_food_network/reports/line_items.rb
|
||||
- lib/open_food_network/sales_tax_report.rb
|
||||
@@ -346,10 +339,8 @@ Metrics/LineLength:
|
||||
- spec/models/tag_rule/filter_shipping_methods_spec.rb
|
||||
- spec/models/variant_override_spec.rb
|
||||
- spec/performance/orders_controller_spec.rb
|
||||
- spec/performance/proxy_order_syncer_spec.rb
|
||||
- spec/performance/shop_controller_spec.rb
|
||||
- spec/requests/checkout/failed_checkout_spec.rb
|
||||
- spec/requests/checkout/paypal_spec.rb
|
||||
- spec/requests/checkout/stripe_connect_spec.rb
|
||||
- spec/requests/embedded_shopfronts_headers_spec.rb
|
||||
- spec/requests/shop_spec.rb
|
||||
@@ -445,7 +436,6 @@ Metrics/AbcSize:
|
||||
- app/models/spree/order_decorator.rb
|
||||
- app/models/spree/payment_decorator.rb
|
||||
- app/models/spree/product_decorator.rb
|
||||
- app/models/spree/product_set.rb
|
||||
- app/models/spree/taxon_decorator.rb
|
||||
- app/serializers/api/admin/enterprise_serializer.rb
|
||||
- app/serializers/api/product_serializer.rb
|
||||
@@ -468,6 +458,7 @@ Metrics/AbcSize:
|
||||
- lib/open_food_network/orders_and_fulfillments_report.rb
|
||||
- lib/open_food_network/packing_report.rb
|
||||
- lib/open_food_network/payments_report.rb
|
||||
- lib/open_food_network/permissions.rb
|
||||
- lib/open_food_network/products_and_inventory_report.rb
|
||||
- lib/open_food_network/reports/line_items.rb
|
||||
- lib/open_food_network/sales_tax_report.rb
|
||||
@@ -566,6 +557,7 @@ Metrics/CyclomaticComplexity:
|
||||
- app/helpers/checkout_helper.rb
|
||||
- app/helpers/i18n_helper.rb
|
||||
- app/helpers/order_cycles_helper.rb
|
||||
- app/helpers/spree/admin/navigation_helper_decorator.rb
|
||||
- app/models/enterprise.rb
|
||||
- app/models/enterprise_relationship.rb
|
||||
- app/models/product_import/entry_processor.rb
|
||||
@@ -573,7 +565,6 @@ Metrics/CyclomaticComplexity:
|
||||
- app/models/spree/ability_decorator.rb
|
||||
- app/models/spree/payment_decorator.rb
|
||||
- app/models/spree/product_decorator.rb
|
||||
- app/models/spree/product_set.rb
|
||||
- app/models/variant_override_set.rb
|
||||
- app/services/cart_service.rb
|
||||
- lib/discourse/single_sign_on.rb
|
||||
@@ -601,7 +592,6 @@ Metrics/PerceivedComplexity:
|
||||
- app/models/spree/ability_decorator.rb
|
||||
- app/models/spree/order_decorator.rb
|
||||
- app/models/spree/product_decorator.rb
|
||||
- app/models/spree/product_set.rb
|
||||
- lib/discourse/single_sign_on.rb
|
||||
- lib/open_food_network/bulk_coop_report.rb
|
||||
- lib/open_food_network/enterprise_issue_validator.rb
|
||||
@@ -657,7 +647,6 @@ Metrics/MethodLength:
|
||||
- app/models/spree/payment_decorator.rb
|
||||
- app/models/spree/payment_method_decorator.rb
|
||||
- app/models/spree/product_decorator.rb
|
||||
- app/models/spree/product_set.rb
|
||||
- app/serializers/api/admin/order_cycle_serializer.rb
|
||||
- app/serializers/api/cached_enterprise_serializer.rb
|
||||
- app/services/order_cycle_form.rb
|
||||
|
||||
@@ -42,6 +42,6 @@ $ docker-compose up
|
||||
```
|
||||
|
||||
This command will setup the database and seed it with sample data. The default admin user is 'ofn@example.com' with 'ofn123' password.
|
||||
Check the app in the browser at `http:://localhost:3000`.
|
||||
Check the app in the browser at `http://localhost:3000`.
|
||||
|
||||
You will then get the trace of the containers in the terminal. You can stop the containers using Ctrl-C in the terminal.
|
||||
|
||||
7
Gemfile
7
Gemfile
@@ -24,7 +24,6 @@ gem 'spree_api', github: 'openfoodfoundation/spree', branch: '2-0-4-stable'
|
||||
gem 'spree_backend', github: 'openfoodfoundation/spree', branch: '2-0-4-stable'
|
||||
gem 'spree_core', github: 'openfoodfoundation/spree', branch: '2-0-4-stable'
|
||||
|
||||
gem 'spree_auth_devise', github: 'spree/spree_auth_devise', branch: '2-0-stable'
|
||||
gem 'spree_i18n', github: 'spree/spree_i18n', branch: '1-3-stable'
|
||||
|
||||
# Our branch contains two changes
|
||||
@@ -37,6 +36,8 @@ gem 'stripe'
|
||||
# which is needed for Pin Payments (and possibly others).
|
||||
gem 'activemerchant', '~> 1.78'
|
||||
|
||||
gem 'devise', '~> 2.2.5'
|
||||
gem 'devise-encryptable', '0.2.0'
|
||||
gem 'jwt', '~> 2.2'
|
||||
gem 'oauth2', '~> 1.4.1' # Used for Stripe Connect
|
||||
|
||||
@@ -118,6 +119,10 @@ gem 'jquery-rails', '3.0.4'
|
||||
|
||||
gem 'ofn-qz', github: 'openfoodfoundation/ofn-qz', ref: '60da2ae4c44cbb4c8d602f59fb5fff8d0f21db3c'
|
||||
|
||||
group :production, :staging do
|
||||
gem 'ddtrace'
|
||||
end
|
||||
|
||||
group :test, :development do
|
||||
# Pretty printed test output
|
||||
gem 'atomic'
|
||||
|
||||
49
Gemfile.lock
49
Gemfile.lock
@@ -31,7 +31,7 @@ GIT
|
||||
|
||||
GIT
|
||||
remote: https://github.com/openfoodfoundation/spree.git
|
||||
revision: 46d6f8f5fd434105b0c69958276d1727a3066a97
|
||||
revision: 8a8585a43cd04d1a50dc65227f337a91b18d66d5
|
||||
branch: 2-0-4-stable
|
||||
specs:
|
||||
spree_api (2.0.4)
|
||||
@@ -66,26 +66,6 @@ GIT
|
||||
state_machine (= 1.2.0)
|
||||
stringex (~> 1.5.1)
|
||||
truncate_html (= 0.9.2)
|
||||
spree_frontend (2.0.4)
|
||||
canonical-rails
|
||||
deface (>= 0.9.0)
|
||||
jquery-rails (~> 3.0.0)
|
||||
rails (~> 3.2.13)
|
||||
spree_api (= 2.0.4)
|
||||
spree_core (= 2.0.4)
|
||||
stringex (~> 1.5.1)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/spree/spree_auth_devise.git
|
||||
revision: 0181835fb6ac77a05191d26f6f32a0f4a548d851
|
||||
branch: 2-0-stable
|
||||
specs:
|
||||
spree_auth_devise (2.0.0)
|
||||
devise (~> 2.2.5)
|
||||
devise-encryptable (= 0.1.2)
|
||||
spree_backend (~> 2.0.0)
|
||||
spree_core (~> 2.0.0)
|
||||
spree_frontend (~> 2.0.0)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/spree/spree_i18n.git
|
||||
@@ -180,7 +160,7 @@ GEM
|
||||
json (~> 1.4)
|
||||
nokogiri (>= 1.4.4)
|
||||
uuidtools (~> 2.1)
|
||||
bcrypt (3.1.11)
|
||||
bcrypt (3.1.13)
|
||||
bcrypt-ruby (3.1.5)
|
||||
bcrypt (>= 3.1.3)
|
||||
blockenspiel (0.5.0)
|
||||
@@ -189,8 +169,6 @@ GEM
|
||||
builder (3.0.4)
|
||||
byebug (9.0.6)
|
||||
cancan (1.6.10)
|
||||
canonical-rails (0.1.0)
|
||||
rails (>= 3.1, < 5.1)
|
||||
capybara (2.18.0)
|
||||
addressable
|
||||
mini_mime (>= 0.1.3)
|
||||
@@ -245,6 +223,8 @@ GEM
|
||||
activerecord (>= 3.2.0, < 5.0)
|
||||
fog (~> 1.0)
|
||||
rails (>= 3.2.0, < 5.0)
|
||||
ddtrace (0.26.0)
|
||||
msgpack
|
||||
debugger-linecache (1.2.0)
|
||||
deface (1.0.2)
|
||||
colorize (>= 0.5.8)
|
||||
@@ -266,7 +246,7 @@ GEM
|
||||
orm_adapter (~> 0.1)
|
||||
railties (~> 3.1)
|
||||
warden (~> 1.2.1)
|
||||
devise-encryptable (0.1.2)
|
||||
devise-encryptable (0.2.0)
|
||||
devise (>= 2.1.0)
|
||||
diff-lcs (1.3)
|
||||
diffy (3.3.0)
|
||||
@@ -476,7 +456,7 @@ GEM
|
||||
rspec (>= 2.99.0, < 4.0)
|
||||
haml (4.0.7)
|
||||
tilt
|
||||
hashdiff (0.4.0)
|
||||
hashdiff (1.0.0)
|
||||
highline (1.6.18)
|
||||
hike (1.2.3)
|
||||
http_parser.rb (0.6.0)
|
||||
@@ -527,11 +507,12 @@ GEM
|
||||
railties (>= 3.1)
|
||||
money (5.1.1)
|
||||
i18n (~> 0.6.0)
|
||||
msgpack (1.3.1)
|
||||
multi_json (1.13.1)
|
||||
multi_xml (0.6.0)
|
||||
multipart-post (2.1.1)
|
||||
nenv (0.3.0)
|
||||
net-http-persistent (3.0.1)
|
||||
net-http-persistent (3.1.0)
|
||||
connection_pool (~> 2.2)
|
||||
newrelic_rpm (3.18.1.330)
|
||||
nokogiri (1.6.8.1)
|
||||
@@ -577,7 +558,7 @@ GEM
|
||||
pry-byebug (3.4.3)
|
||||
byebug (>= 9.0, < 9.1)
|
||||
pry (~> 0.10)
|
||||
public_suffix (3.0.3)
|
||||
public_suffix (3.1.1)
|
||||
rabl (0.8.4)
|
||||
activesupport (>= 2.3.14)
|
||||
rack (1.4.7)
|
||||
@@ -613,7 +594,7 @@ GEM
|
||||
thor (>= 0.14.6, < 2.0)
|
||||
rainbow (3.0.0)
|
||||
raindrops (0.19.0)
|
||||
rake (12.3.2)
|
||||
rake (12.3.3)
|
||||
ransack (0.7.2)
|
||||
actionpack (~> 3.0)
|
||||
activerecord (~> 3.0)
|
||||
@@ -628,7 +609,7 @@ GEM
|
||||
trollop (~> 2.1)
|
||||
rdoc (3.12.2)
|
||||
json (~> 1.4)
|
||||
redcarpet (3.4.0)
|
||||
redcarpet (3.5.0)
|
||||
ref (2.0.0)
|
||||
request_store (1.4.1)
|
||||
rack (>= 1.4)
|
||||
@@ -720,7 +701,7 @@ GEM
|
||||
tilt (~> 1.1, != 1.3.0)
|
||||
state_machine (1.2.0)
|
||||
stringex (1.5.1)
|
||||
stripe (4.19.0)
|
||||
stripe (4.24.0)
|
||||
faraday (~> 0.13)
|
||||
net-http-persistent (~> 3.0)
|
||||
therubyracer (0.12.0)
|
||||
@@ -758,7 +739,7 @@ GEM
|
||||
nokogiri (~> 1.6)
|
||||
rubyzip (~> 1.0)
|
||||
selenium-webdriver (~> 3.0)
|
||||
webmock (3.6.0)
|
||||
webmock (3.6.2)
|
||||
addressable (>= 2.3.6)
|
||||
crack (>= 0.3.2)
|
||||
hashdiff (>= 0.4.0, < 2.0.0)
|
||||
@@ -797,10 +778,13 @@ DEPENDENCIES
|
||||
dalli
|
||||
database_cleaner (= 0.7.1)
|
||||
db2fog
|
||||
ddtrace
|
||||
debugger-linecache
|
||||
deface (= 1.0.2)
|
||||
delayed_job_active_record
|
||||
delayed_job_web
|
||||
devise (~> 2.2.5)
|
||||
devise-encryptable (= 0.2.0)
|
||||
diffy
|
||||
eventmachine (>= 1.2.3)
|
||||
factory_bot_rails
|
||||
@@ -861,7 +845,6 @@ DEPENDENCIES
|
||||
skylight (< 2.0)
|
||||
spinjs-rails
|
||||
spree_api!
|
||||
spree_auth_devise!
|
||||
spree_backend!
|
||||
spree_core!
|
||||
spree_i18n!
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
//= require angular-animate
|
||||
//= require angular-sanitize
|
||||
//= require admin/spree_backend
|
||||
//= require admin/spree_auth
|
||||
//= require admin/spree_paypal_express
|
||||
//= require ../shared/ng-infinite-scroll.min.js
|
||||
//= require ../shared/ng-tags-input.min.js
|
||||
|
||||
@@ -24,8 +24,3 @@ angular.module("admin.orders").controller "orderCtrl", ($scope, shops, orderCycl
|
||||
|
||||
for shop in $scope.shops
|
||||
shop.disabled = !$scope.distributorHasOrderCycles(shop)
|
||||
|
||||
# Removes the split button introduced by spree in the order form
|
||||
# We only have one stock location in OFN so it's meaningless to split the order between stock locations
|
||||
# We delete it instead of hiding or changing CSS so that, when spree code toggles the element, nothing hapens
|
||||
$('.split-item').remove()
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
angular.module("admin.products").directive "setOnDemand", ->
|
||||
link: (scope, element, attr) ->
|
||||
onHand = element.context.querySelector("#variant_on_hand")
|
||||
onDemand = element.context.querySelector("#variant_on_demand")
|
||||
|
||||
disableOnHandIfOnDemand = ->
|
||||
if onDemand.checked
|
||||
onHand.disabled = 'disabled'
|
||||
onHand.dataStock = onHand.value
|
||||
onHand.value = t('admin.products.variants.infinity')
|
||||
|
||||
disableOnHandIfOnDemand()
|
||||
|
||||
onDemand.addEventListener 'change', (event) ->
|
||||
disableOnHandIfOnDemand()
|
||||
|
||||
if !onDemand.checked
|
||||
onHand.removeAttribute('disabled')
|
||||
onHand.value = onHand.dataStock
|
||||
@@ -5,7 +5,7 @@ angular.module("admin.subscriptions").controller "OrderUpdateIssuesController",
|
||||
OrderCycles.byID[id].name
|
||||
|
||||
$scope.orderCycleCloses = (id) ->
|
||||
closes_at = moment(OrderCycles.byID[id].orders_close_at)
|
||||
closes_at = moment(OrderCycles.byID[id].orders_close_at, "YYYY-MM-DD HH:mm:SS Z")
|
||||
key = if closes_at > moment() then "closes" else "closed"
|
||||
text = t("js.subscriptions." + key)
|
||||
"#{text} #{closes_at.fromNow()}"
|
||||
|
||||
@@ -15,7 +15,7 @@ angular.module("admin.subscriptions").controller "OrdersPanelController", ($scop
|
||||
$scope.orderCycleCloses = (id) ->
|
||||
oc = OrderCycles.byID[id]
|
||||
return t('js.subscriptions.close_date_not_set') unless oc?.orders_close_at?
|
||||
closes_at = moment(oc.orders_close_at)
|
||||
closes_at = moment(oc.orders_close_at, "YYYY-MM-DD HH:mm:SS Z")
|
||||
text = if closes_at > moment() then t('js.subscriptions.closes') else t('js.subscriptions.closed')
|
||||
"#{text} #{closes_at.fromNow()}"
|
||||
|
||||
|
||||
@@ -27,8 +27,6 @@ angular.module("admin.utils").directive "variantAutocomplete", ($timeout) ->
|
||||
window.variants = data # this is how spree auto complete JS code picks up variants
|
||||
results: data
|
||||
formatResult: (variant) ->
|
||||
if variant["images"][0] != undefined && variant["images"][0].image != undefined
|
||||
variant.image = variant.images[0].image.mini_url
|
||||
variantTemplate variant: variant
|
||||
formatSelection: (variant) ->
|
||||
element.parent().children(".options_placeholder").html variant.options_text
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
Darkswarm.controller "OffcanvasCtrl", ($scope) ->
|
||||
$scope.menu = $(".left-off-canvas-menu")
|
||||
|
||||
$scope.setOffcanvasMenuHeight = ->
|
||||
$scope.menu.height($(window).height())
|
||||
|
||||
$scope.bind = ->
|
||||
$(window).on("resize", $scope.setOffcanvasMenuHeight)
|
||||
$scope.setOffcanvasMenuHeight()
|
||||
|
||||
$scope.bind()
|
||||
@@ -1,8 +0,0 @@
|
||||
Darkswarm.directive "cart", ->
|
||||
# Toggles visibility of the "cart" popover
|
||||
restrict: 'A'
|
||||
link: (scope, elem, attr)->
|
||||
scope.open = false
|
||||
elem.bind 'click', ->
|
||||
scope.$apply ->
|
||||
scope.open = !scope.open
|
||||
@@ -0,0 +1,19 @@
|
||||
Darkswarm.directive "cartToggle", ($document) ->
|
||||
# Toggles visibility of the "cart" popover
|
||||
restrict: 'A'
|
||||
link: (scope, elem, attr)->
|
||||
scope.open = false
|
||||
|
||||
$document.bind 'click', (event) ->
|
||||
cart_button = elem[0]
|
||||
element_and_parents = [event.target, event.target.parentElement, event.target.parentElement.parentElement]
|
||||
cart_button_clicked = (element_and_parents.indexOf(cart_button) != -1)
|
||||
|
||||
if cart_button_clicked
|
||||
scope.$apply ->
|
||||
scope.open = !scope.open
|
||||
else
|
||||
scope.$apply ->
|
||||
scope.open = false
|
||||
|
||||
return
|
||||
@@ -2,7 +2,14 @@ Darkswarm.directive "ofnPageAlert", ($timeout) ->
|
||||
restrict: 'A'
|
||||
scope: true
|
||||
link: (scope, elem, attrs) ->
|
||||
container_elems = $(".off-canvas-wrap .inner-wrap, .off-canvas-wrap .inner-wrap .fixed, .page-alert")
|
||||
moveSelectors = [".off-canvas-wrap .inner-wrap",
|
||||
".off-canvas-wrap .inner-wrap .fixed",
|
||||
".off-canvas-fixed .top-bar",
|
||||
".off-canvas-fixed ofn-flash",
|
||||
".off-canvas-fixed nav.tab-bar",
|
||||
".off-canvas-fixed .page-alert"]
|
||||
|
||||
container_elems = $(moveSelectors.join(", "))
|
||||
|
||||
# Wait a moment after page load before showing the alert. Otherwise we often miss the
|
||||
# start of the animation.
|
||||
|
||||
@@ -5,12 +5,10 @@
|
||||
*
|
||||
|
||||
*= require admin/spree_backend
|
||||
*= require admin/spree_auth
|
||||
|
||||
*= require jquery-ui-timepicker-addon
|
||||
*= require shared/textAngular
|
||||
*= require shared/ng-tags-input.min
|
||||
*= require admin/custom
|
||||
|
||||
*= require_self
|
||||
*/
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
/* Custom fix */
|
||||
.ui-timepicker-div.ui-timepicker-oneLine dl dd { width: 25%; }
|
||||
@@ -0,0 +1,11 @@
|
||||
.add-line-item {
|
||||
fieldset {
|
||||
.vertical-align-top {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.actions {
|
||||
padding-top: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
@import 'foundation-icons';
|
||||
|
||||
@import 'base/*';
|
||||
@import 'layout/*';
|
||||
@import '*';
|
||||
@import 'pages/*';
|
||||
@import '../web/all';
|
||||
|
||||
@@ -35,5 +35,6 @@ $med-grey: #666;
|
||||
$med-drk-grey: #444;
|
||||
$dark-grey: #333;
|
||||
$light-grey: #ddd;
|
||||
$light-grey-transparency: rgba(0, 0, 0, .1);
|
||||
$black: #000;
|
||||
$white: #fff;
|
||||
|
||||
17
app/assets/stylesheets/darkswarm/layout/offcanvas.css.scss
Normal file
17
app/assets/stylesheets/darkswarm/layout/offcanvas.css.scss
Normal file
@@ -0,0 +1,17 @@
|
||||
@import "compass/css3/transition";
|
||||
|
||||
.off-canvas-fixed {
|
||||
@include transition(transform 1000ms ease-in-out);
|
||||
}
|
||||
|
||||
.move-right > .off-canvas-fixed {
|
||||
height: 100%;
|
||||
-webkit-transform: translate3d(15.625rem, 0, 0);
|
||||
transform: translate3d(15.625rem, 0, 0);
|
||||
}
|
||||
|
||||
.left-off-canvas-menu {
|
||||
-webkit-transform: none;
|
||||
transform: none;
|
||||
margin-left: -15.625rem;
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
@import "compass";
|
||||
@import "branding";
|
||||
@import "mixins";
|
||||
@import "typography";
|
||||
@import "variables";
|
||||
@import 'compass';
|
||||
@import 'branding';
|
||||
@import 'mixins';
|
||||
@import 'typography';
|
||||
@import 'variables';
|
||||
|
||||
nav.top-bar {
|
||||
@include textpress;
|
||||
@@ -42,6 +42,8 @@ nav.top-bar {
|
||||
}
|
||||
|
||||
.top-bar-section {
|
||||
border-bottom: 1px solid $light-grey-transparency;
|
||||
|
||||
a.icon {
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
@@ -168,12 +170,18 @@ nav.top-bar {
|
||||
|
||||
.tab-bar {
|
||||
background-color: white;
|
||||
border-bottom: 1px solid $light-grey-transparency;
|
||||
height: 2.8em;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
|
||||
.cart-span {
|
||||
background-color: #f4704c;
|
||||
padding: 13px;
|
||||
|
||||
a, span {
|
||||
a,
|
||||
span {
|
||||
color: white;
|
||||
display: inline-block;
|
||||
}
|
||||
@@ -202,7 +210,6 @@ nav.top-bar {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.off-canvas-list li.language-switcher ul li {
|
||||
list-style-type: none;
|
||||
padding-left: 0.5em;
|
||||
@@ -228,10 +235,19 @@ nav.top-bar {
|
||||
padding: 9px 0 0 9px;
|
||||
}
|
||||
|
||||
// Leave space for tab bar, in screens smaller than large.
|
||||
[role="main"] {
|
||||
margin-top: 2.8em;
|
||||
|
||||
@media #{$large-up} {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.top-bar .ofn-logo img {
|
||||
height: auto;
|
||||
width: auto;
|
||||
max-height: 51px;
|
||||
max-height: 44px;
|
||||
max-width: 250px;
|
||||
}
|
||||
|
||||
@@ -239,7 +255,7 @@ nav.top-bar {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.off-canvas-wrap.move-right ul.off-canvas-list {
|
||||
.off-canvas-wrap ul.off-canvas-list {
|
||||
font-size: 0.875rem;
|
||||
|
||||
.li-menu {
|
||||
@@ -259,12 +275,10 @@ nav.top-bar {
|
||||
background-color: transparent;
|
||||
color: $brand-colour;
|
||||
}
|
||||
|
||||
@include transition(all 0.3s ease-in-out);
|
||||
}
|
||||
}
|
||||
|
||||
.off-canvas-wrap.move-right ul.off-canvas-list i {
|
||||
.off-canvas-wrap ul.off-canvas-list i {
|
||||
font-size: 1.5rem;
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
@@ -273,7 +287,8 @@ nav.top-bar {
|
||||
|
||||
@media screen and (max-width: 1450px) {
|
||||
nav .top-bar-section {
|
||||
ul li a, .has-dropdown > a {
|
||||
ul li a,
|
||||
.has-dropdown > a {
|
||||
padding: 0 ($topbar-height / 8) !important;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
@import "animations";
|
||||
@import "compass/css3/transition";
|
||||
|
||||
$page-alert-height: 55px;
|
||||
|
||||
// Basic style \\
|
||||
.page-alert {
|
||||
.alert-box {
|
||||
height: 55px;
|
||||
height: $page-alert-height;
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba($dark-grey, 0.35);
|
||||
border-left: none;
|
||||
@@ -45,33 +47,26 @@
|
||||
}
|
||||
|
||||
// Show-hide animation \\
|
||||
.off-canvas-wrap .inner-wrap, .off-canvas-wrap .inner-wrap .fixed, nav.tab-bar {
|
||||
@include transition(all, 1000ms, ease-in-out);
|
||||
|
||||
.off-canvas-wrap .inner-wrap,
|
||||
.off-canvas-fixed .top-bar,
|
||||
.off-canvas-fixed ofn-flash,
|
||||
.off-canvas-fixed nav.tab-bar,
|
||||
.off-canvas-fixed .page-alert {
|
||||
@include transition(all 1000ms ease-in-out);
|
||||
|
||||
&.move-down {
|
||||
margin-top: 55px;
|
||||
|
||||
@include transition(all, 1000ms, ease-in-out);
|
||||
margin-top: $page-alert-height;
|
||||
}
|
||||
}
|
||||
|
||||
.off-canvas-wrap .inner-wrap .page-alert.fixed {
|
||||
top: -55px;
|
||||
z-index: 1;
|
||||
|
||||
// TODO: Compass to disable transition
|
||||
-moz-transition: none;
|
||||
-webkit-transition: none;
|
||||
-o-transition: color 0 ease-in;
|
||||
transition: none;
|
||||
.off-canvas-wrap .page-alert {
|
||||
top: -1 * $page-alert-height;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.off-canvas-wrap.move-right .inner-wrap.move-down {
|
||||
.page-alert {
|
||||
top: -55px * 2;
|
||||
}
|
||||
|
||||
.left-off-canvas-menu {
|
||||
top: -55px;
|
||||
top: -1 * $page-alert-height;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@import "mixins";
|
||||
@import "branding";
|
||||
@import "compass/css3/user-interface";
|
||||
@import 'variables';
|
||||
|
||||
.cart {
|
||||
@include user-select(none);
|
||||
@@ -15,8 +16,8 @@
|
||||
|
||||
.joyride-tip-guide {
|
||||
display: block;
|
||||
right: 10px;
|
||||
top: 55px;
|
||||
right: 0;
|
||||
top: $topbar-height;
|
||||
width: 480px;
|
||||
|
||||
@media screen and (min-width: 641px) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
require 'open_food_network/permissions'
|
||||
require 'open_food_network/proxy_order_syncer'
|
||||
|
||||
module Admin
|
||||
class SubscriptionsController < ResourceController
|
||||
@@ -32,21 +33,11 @@ module Admin
|
||||
end
|
||||
|
||||
def create
|
||||
form = SubscriptionForm.new(@subscription, params[:subscription])
|
||||
if form.save
|
||||
render_as_json @subscription
|
||||
else
|
||||
render json: { errors: form.json_errors }, status: :unprocessable_entity
|
||||
end
|
||||
save_form_and_render(false)
|
||||
end
|
||||
|
||||
def update
|
||||
form = SubscriptionForm.new(@subscription, params[:subscription])
|
||||
if form.save
|
||||
render_as_json @subscription, order_update_issues: form.order_update_issues
|
||||
else
|
||||
render json: { errors: form.json_errors }, status: :unprocessable_entity
|
||||
end
|
||||
save_form_and_render
|
||||
end
|
||||
|
||||
def cancel
|
||||
@@ -67,12 +58,26 @@ module Admin
|
||||
end
|
||||
|
||||
def unpause
|
||||
@subscription.update_attributes(paused_at: nil)
|
||||
render_as_json @subscription
|
||||
params[:subscription][:paused_at] = nil
|
||||
save_form_and_render
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def save_form_and_render(render_issues = true)
|
||||
form = SubscriptionForm.new(@subscription, params[:subscription])
|
||||
unless form.save
|
||||
render json: { errors: form.json_errors }, status: :unprocessable_entity
|
||||
return
|
||||
end
|
||||
|
||||
if render_issues
|
||||
render_as_json @subscription, order_update_issues: form.order_update_issues
|
||||
else
|
||||
render_as_json @subscription
|
||||
end
|
||||
end
|
||||
|
||||
def permissions
|
||||
return @permissions unless @permissions.nil?
|
||||
@permissions = OpenFoodNetwork::Permissions.new(spree_current_user)
|
||||
|
||||
@@ -9,8 +9,8 @@ module Admin
|
||||
def map_by_tag
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
serialiser = ActiveModel::ArraySerializer.new(collection)
|
||||
render json: serialiser.to_json
|
||||
serializer = ActiveModel::ArraySerializer.new(collection)
|
||||
render json: serializer.to_json
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,12 +5,7 @@ module Api
|
||||
before_filter :override_sells, only: [:create, :update]
|
||||
before_filter :override_visible, only: [:create, :update]
|
||||
respond_to :json
|
||||
skip_authorization_check only: [:shopfront, :managed]
|
||||
|
||||
def managed
|
||||
@enterprises = Enterprise.ransack(params[:q]).result.managed_by(current_api_user)
|
||||
render params[:template] || :bulk_index
|
||||
end
|
||||
skip_authorization_check only: [:shopfront]
|
||||
|
||||
def create
|
||||
authorize! :create, Enterprise
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
module Api
|
||||
class OrderCyclesController < Spree::Api::BaseController
|
||||
respond_to :json
|
||||
def managed
|
||||
authorize! :admin, OrderCycle
|
||||
authorize! :read, OrderCycle
|
||||
@order_cycles = OrderCycle.ransack(params[:q]).result.managed_by(current_api_user)
|
||||
render params[:template] || :bulk_index
|
||||
end
|
||||
|
||||
def accessible
|
||||
@order_cycles = if params[:as] == "distributor"
|
||||
OrderCycle.ransack(params[:q]).result.
|
||||
involving_managed_distributors_of(current_api_user).order('updated_at DESC')
|
||||
elsif params[:as] == "producer"
|
||||
OrderCycle.ransack(params[:q]).result.
|
||||
involving_managed_producers_of(current_api_user).order('updated_at DESC')
|
||||
else
|
||||
OrderCycle.ransack(params[:q]).result.accessible_by(current_api_user)
|
||||
end
|
||||
|
||||
render params[:template] || :bulk_index
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,5 +1,5 @@
|
||||
module Api
|
||||
class ProductImagesController < Spree::Api::BaseController
|
||||
class ProductImagesController < BaseController
|
||||
respond_to :json
|
||||
|
||||
def update_product_image
|
||||
@@ -8,11 +8,11 @@ module Api
|
||||
|
||||
if @product.images.first.nil?
|
||||
@image = Spree::Image.create(attachment: params[:file], viewable_id: @product.master.id, viewable_type: 'Spree::Variant')
|
||||
respond_with(@image, status: 201)
|
||||
render json: @image, serializer: ImageSerializer, status: :created
|
||||
else
|
||||
@image = @product.images.first
|
||||
@image.update_attributes(attachment: params[:file])
|
||||
respond_with(@image, status: 200)
|
||||
render json: @image, serializer: ImageSerializer, status: :ok
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
require 'open_food_network/referer_parser'
|
||||
require 'spree/authentication_helpers'
|
||||
|
||||
class ApplicationController < ActionController::Base
|
||||
protect_from_forgery
|
||||
@@ -7,6 +8,7 @@ class ApplicationController < ActionController::Base
|
||||
before_filter :set_cache_headers # prevent cart emptying via cache when using back button #1213
|
||||
|
||||
include EnterprisesHelper
|
||||
include Spree::AuthenticationHelpers
|
||||
|
||||
def redirect_to(options = {}, response_status = {})
|
||||
::Rails.logger.error("Redirected by #{begin
|
||||
|
||||
@@ -8,7 +8,6 @@ class CheckoutController < Spree::CheckoutController
|
||||
prepend_before_filter :require_order_cycle
|
||||
prepend_before_filter :require_distributor_chosen
|
||||
|
||||
skip_before_filter :check_registration
|
||||
before_filter :enable_embedded_shopfront
|
||||
|
||||
include OrderCyclesHelper
|
||||
|
||||
6
app/controllers/metal_decorator.rb
Normal file
6
app/controllers/metal_decorator.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
# For the API
|
||||
ActionController::Metal.class_eval do
|
||||
def spree_current_user
|
||||
@spree_current_user ||= env['warden'].user
|
||||
end
|
||||
end
|
||||
@@ -27,12 +27,12 @@ class ShopController < BaseController
|
||||
if oc = OrderCycle.with_distributor(@distributor).active.find_by_id(params[:order_cycle_id])
|
||||
current_order(true).set_order_cycle! oc
|
||||
@current_order_cycle = oc
|
||||
render partial: "json/order_cycle"
|
||||
render json: @current_order_cycle, serializer: Api::OrderCycleSerializer
|
||||
else
|
||||
render status: :not_found, json: ""
|
||||
end
|
||||
else
|
||||
render partial: "json/order_cycle"
|
||||
render json: current_order_cycle, serializer: Api::OrderCycleSerializer
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -47,11 +47,21 @@ Spree::Admin::BaseController.class_eval do
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def model_class
|
||||
const_name = controller_name.classify
|
||||
if Spree.const_defined?(const_name)
|
||||
return "Spree::#{const_name}".constantize
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def active_distributors_not_ready_for_checkout
|
||||
ocs = OrderCycle.managed_by(spree_current_user).active
|
||||
distributors = ocs.map(&:distributors).flatten.uniq
|
||||
distributors = ocs.includes(:distributors).map(&:distributors).flatten.uniq
|
||||
Enterprise.where('enterprises.id IN (?)', distributors).not_ready_for_checkout
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Spree::Admin::Orders::CustomerDetailsController.class_eval do
|
||||
before_filter :check_authorization
|
||||
before_filter :set_guest_checkout_status, only: :update
|
||||
|
||||
def update
|
||||
@@ -25,6 +26,17 @@ Spree::Admin::Orders::CustomerDetailsController.class_eval do
|
||||
|
||||
private
|
||||
|
||||
def check_authorization
|
||||
load_order
|
||||
session[:access_token] ||= params[:token]
|
||||
|
||||
resource = @order
|
||||
action = params[:action].to_sym
|
||||
action = :edit if action == :show # show route renders :edit for this controller
|
||||
|
||||
authorize! action, resource, session[:access_token]
|
||||
end
|
||||
|
||||
def set_guest_checkout_status
|
||||
registered_user = Spree::User.find_by_email(params[:order][:email])
|
||||
|
||||
|
||||
@@ -48,19 +48,13 @@ Spree::Admin::ProductsController.class_eval do
|
||||
end
|
||||
|
||||
def bulk_update
|
||||
collection_hash = Hash[params[:products].each_with_index.map { |p, i| [i, p] }]
|
||||
product_set = Spree::ProductSet.new(collection_attributes: collection_hash)
|
||||
|
||||
params[:filters] ||= {}
|
||||
bulk_index_query = params[:filters].reduce("") do |string, filter|
|
||||
"#{string}q[#{filter[:property][:db_column]}_#{filter[:predicate][:predicate]}]=#{filter[:value]};"
|
||||
end
|
||||
product_set = product_set_from_params(params)
|
||||
|
||||
# Ensure we're authorised to update all products
|
||||
product_set.collection.each { |p| authorize! :update, p }
|
||||
|
||||
if product_set.save
|
||||
redirect_to "/api/products/bulk_products?page=1;per_page=500;#{bulk_index_query}"
|
||||
redirect_to "/api/products/bulk_products?page=1;per_page=500;#{bulk_index_query(params)}"
|
||||
else
|
||||
if product_set.errors.present?
|
||||
render json: { errors: product_set.errors }, status: :bad_request
|
||||
@@ -73,7 +67,8 @@ Spree::Admin::ProductsController.class_eval do
|
||||
protected
|
||||
|
||||
def collection
|
||||
# This method is copied directly from the spree product controller, except where we narrow the search below with the managed_by search to support
|
||||
# This method is copied directly from the spree product controller
|
||||
# except where we narrow the search below with the managed_by search to support
|
||||
# enterprise users.
|
||||
# TODO: There has to be a better way!!!
|
||||
return @collection if @collection.present?
|
||||
@@ -108,14 +103,38 @@ Spree::Admin::ProductsController.class_eval do
|
||||
|
||||
private
|
||||
|
||||
def product_set_from_params(params)
|
||||
collection_hash = Hash[params[:products].each_with_index.map { |p, i| [i, p] }]
|
||||
Spree::ProductSet.new(collection_attributes: collection_hash)
|
||||
end
|
||||
|
||||
def bulk_index_query(params)
|
||||
params[:filters] ||= {}
|
||||
params[:filters].reduce("") do |string, filter|
|
||||
filter_db_column = filter[:property][:db_column]
|
||||
filter_predicate = filter[:predicate][:predicate]
|
||||
filter_value = filter[:value]
|
||||
"#{string}q[#{filter_db_column}_#{filter_predicate}]=#{filter_value};"
|
||||
end
|
||||
end
|
||||
|
||||
def load_form_data
|
||||
@producers = OpenFoodNetwork::Permissions.new(spree_current_user).managed_product_enterprises.is_primary_producer.by_name
|
||||
@producers = OpenFoodNetwork::Permissions.new(spree_current_user).
|
||||
managed_product_enterprises.is_primary_producer.by_name
|
||||
@taxons = Spree::Taxon.order(:name)
|
||||
@import_dates = product_import_dates.uniq.to_json
|
||||
end
|
||||
|
||||
def product_import_dates
|
||||
import_dates = Spree::Variant.
|
||||
options = [{ id: '0', name: '' }]
|
||||
product_import_dates_query.collect(&:import_date).
|
||||
map { |i| options.push(id: i.to_date, name: i.to_date.to_formatted_s(:long)) }
|
||||
|
||||
options
|
||||
end
|
||||
|
||||
def product_import_dates_query
|
||||
Spree::Variant.
|
||||
select('DISTINCT spree_variants.import_date').
|
||||
joins(:product).
|
||||
where('spree_products.supplier_id IN (?)', editable_enterprises.collect(&:id)).
|
||||
@@ -123,18 +142,14 @@ Spree::Admin::ProductsController.class_eval do
|
||||
where(spree_variants: { is_master: false }).
|
||||
where(spree_variants: { deleted_at: nil }).
|
||||
order('spree_variants.import_date DESC')
|
||||
|
||||
options = [{ id: '0', name: '' }]
|
||||
import_dates.collect(&:import_date).map { |i| options.push(id: i.to_date, name: i.to_date.to_formatted_s(:long)) }
|
||||
|
||||
options
|
||||
end
|
||||
|
||||
def strip_new_properties
|
||||
unless spree_current_user.admin? || params[:product][:product_properties_attributes].nil?
|
||||
names = Spree::Property.pluck(:name)
|
||||
params[:product][:product_properties_attributes].each do |key, property|
|
||||
params[:product][:product_properties_attributes].delete key unless names.include? property[:property_name]
|
||||
return if spree_current_user.admin? || params[:product][:product_properties_attributes].nil?
|
||||
names = Spree::Property.pluck(:name)
|
||||
params[:product][:product_properties_attributes].each do |key, property|
|
||||
unless names.include? property[:property_name]
|
||||
params[:product][:product_properties_attributes].delete key
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -149,12 +164,32 @@ Spree::Admin::ProductsController.class_eval do
|
||||
end
|
||||
|
||||
def set_stock_levels(product, on_hand, on_demand)
|
||||
variant = product.master
|
||||
if product.variants.any?
|
||||
variant = product.variants.first
|
||||
variant = product_variant(product)
|
||||
|
||||
begin
|
||||
variant.on_demand = on_demand if on_demand.present?
|
||||
variant.on_hand = on_hand.to_i if on_hand.present?
|
||||
rescue StandardError => error
|
||||
notify_bugsnag(error, product, variant)
|
||||
raise error
|
||||
end
|
||||
end
|
||||
|
||||
def notify_bugsnag(error, product, variant)
|
||||
Bugsnag.notify(error) do |report|
|
||||
report.add_tab(:product, product.attributes)
|
||||
report.add_tab(:product_error, product.errors.first) unless product.valid?
|
||||
report.add_tab(:variant, variant.attributes)
|
||||
report.add_tab(:variant_error, variant.errors.first) unless variant.valid?
|
||||
end
|
||||
end
|
||||
|
||||
def product_variant(product)
|
||||
if product.variants.any?
|
||||
product.variants.first
|
||||
else
|
||||
product.master
|
||||
end
|
||||
variant.on_demand = on_demand if on_demand.present?
|
||||
variant.on_hand = on_hand.to_i if on_hand.present?
|
||||
end
|
||||
|
||||
def set_product_master_variant_price_to_zero
|
||||
|
||||
@@ -14,3 +14,7 @@ module AuthorizeOnLoadResource
|
||||
end
|
||||
|
||||
Spree::Admin::ResourceController.prepend(AuthorizeOnLoadResource)
|
||||
|
||||
Spree::Admin::ResourceController.class_eval do
|
||||
rescue_from CanCan::AccessDenied, :with => :unauthorized
|
||||
end
|
||||
|
||||
131
app/controllers/spree/admin/users_controller.rb
Normal file
131
app/controllers/spree/admin/users_controller.rb
Normal file
@@ -0,0 +1,131 @@
|
||||
module Spree
|
||||
module Admin
|
||||
class UsersController < ResourceController
|
||||
rescue_from Spree::User::DestroyWithOrdersError, with: :user_destroy_with_orders_error
|
||||
|
||||
after_filter :sign_in_if_change_own_password, only: :update
|
||||
|
||||
# http://spreecommerce.com/blog/2010/11/02/json-hijacking-vulnerability/
|
||||
before_filter :check_json_authenticity, only: :index
|
||||
before_filter :load_roles, only: [:edit, :new, :update, :create,
|
||||
:generate_api_key, :clear_api_key]
|
||||
|
||||
def index
|
||||
respond_with(@collection) do |format|
|
||||
format.html
|
||||
format.json { render json: json_data }
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
if params[:user]
|
||||
roles = params[:user].delete("spree_role_ids")
|
||||
end
|
||||
|
||||
@user = Spree::User.new(params[:user])
|
||||
if @user.save
|
||||
|
||||
if roles
|
||||
@user.spree_roles = roles.reject(&:blank?).collect{ |r| Spree::Role.find(r) }
|
||||
end
|
||||
|
||||
flash.now[:success] = Spree.t(:created_successfully)
|
||||
render :edit
|
||||
else
|
||||
render :new
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
if params[:user]
|
||||
roles = params[:user].delete("spree_role_ids")
|
||||
end
|
||||
|
||||
if @user.update_attributes(params[:user])
|
||||
if roles
|
||||
@user.spree_roles = roles.reject(&:blank?).collect{ |r| Spree::Role.find(r) }
|
||||
end
|
||||
|
||||
flash.now[:success] = Spree.t(:account_updated)
|
||||
end
|
||||
render :edit
|
||||
end
|
||||
|
||||
def generate_api_key
|
||||
if @user.generate_spree_api_key!
|
||||
flash[:success] = Spree.t('api.key_generated')
|
||||
end
|
||||
redirect_to edit_admin_user_path(@user)
|
||||
end
|
||||
|
||||
def clear_api_key
|
||||
if @user.clear_spree_api_key!
|
||||
flash[:success] = Spree.t('api.key_cleared')
|
||||
end
|
||||
redirect_to edit_admin_user_path(@user)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def collection
|
||||
return @collection if @collection.present?
|
||||
if request.xhr? && params[:q].present?
|
||||
# Disabling proper nested include here due to rails 3.1 bug
|
||||
@collection = Spree::User.
|
||||
includes(:bill_address, :ship_address).
|
||||
where("spree_users.email #{LIKE} :search
|
||||
OR (spree_addresses.firstname #{LIKE} :search
|
||||
AND spree_addresses.id = spree_users.bill_address_id)
|
||||
OR (spree_addresses.lastname #{LIKE} :search
|
||||
AND spree_addresses.id = spree_users.bill_address_id)
|
||||
OR (spree_addresses.firstname #{LIKE} :search
|
||||
AND spree_addresses.id = spree_users.ship_address_id)
|
||||
OR (spree_addresses.lastname #{LIKE} :search
|
||||
AND spree_addresses.id = spree_users.ship_address_id)",
|
||||
search: "#{params[:q].strip}%").
|
||||
limit(params[:limit] || 100)
|
||||
else
|
||||
@search = Spree::User.registered.ransack(params[:q])
|
||||
@collection = @search.
|
||||
result.
|
||||
page(params[:page]).
|
||||
per(Spree::Config[:admin_products_per_page])
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# handling raise from Spree::Admin::ResourceController#destroy
|
||||
def user_destroy_with_orders_error
|
||||
invoke_callbacks(:destroy, :fails)
|
||||
render status: :forbidden, text: Spree.t(:error_user_destroy_with_orders)
|
||||
end
|
||||
|
||||
# Allow different formats of json data to suit different ajax calls
|
||||
def json_data
|
||||
json_format = params[:json_format] || 'default'
|
||||
case json_format
|
||||
when 'basic'
|
||||
collection.map { |u| { 'id' => u.id, 'name' => u.email } }.to_json
|
||||
else
|
||||
address_fields = [:firstname, :lastname, :address1, :address2, :city,
|
||||
:zipcode, :phone, :state_name, :state_id, :country_id]
|
||||
includes = { only: address_fields, include: { state: { only: :name },
|
||||
country: { only: :name } } }
|
||||
|
||||
collection.to_json(only: [:id, :email], include:
|
||||
{ bill_address: includes, ship_address: includes })
|
||||
end
|
||||
end
|
||||
|
||||
def sign_in_if_change_own_password
|
||||
return unless spree_current_user == @user && @user.password.present?
|
||||
sign_in(@user, event: :authentication, bypass: true)
|
||||
end
|
||||
|
||||
def load_roles
|
||||
@roles = Spree::Role.scoped
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -18,6 +18,7 @@ Spree::Admin::VariantsController.class_eval do
|
||||
def search
|
||||
scoper = OpenFoodNetwork::ScopeVariantsForSearch.new(params)
|
||||
@variants = scoper.search
|
||||
render json: @variants, each_serializer: Api::Admin::VariantSerializer
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
||||
44
app/controllers/spree/user_passwords_controller.rb
Normal file
44
app/controllers/spree/user_passwords_controller.rb
Normal file
@@ -0,0 +1,44 @@
|
||||
module Spree
|
||||
class UserPasswordsController < Devise::PasswordsController
|
||||
helper 'spree/base', 'spree/store'
|
||||
|
||||
include Spree::Core::ControllerHelpers::Auth
|
||||
include Spree::Core::ControllerHelpers::Common
|
||||
include Spree::Core::ControllerHelpers::Order
|
||||
include Spree::Core::ControllerHelpers::SSL
|
||||
|
||||
ssl_required
|
||||
|
||||
# Overridden due to bug in Devise.
|
||||
# respond_with resource, :location => new_session_path(resource_name)
|
||||
# is generating bad url /session/new.user
|
||||
#
|
||||
# overridden to:
|
||||
# respond_with resource, :location => spree.login_path
|
||||
#
|
||||
def create
|
||||
self.resource = resource_class.send_reset_password_instructions(params[resource_name])
|
||||
|
||||
if resource.errors.empty?
|
||||
set_flash_message(:notice, :send_instructions) if is_navigational_format?
|
||||
respond_with resource, location: spree.login_path
|
||||
else
|
||||
respond_with_navigational(resource) { render :new }
|
||||
end
|
||||
end
|
||||
|
||||
# Devise::PasswordsController allows for blank passwords.
|
||||
# Silly Devise::PasswordsController!
|
||||
# Fixes spree/spree#2190.
|
||||
def update
|
||||
if params[:spree_user][:password].blank?
|
||||
self.resource = resource_class.new
|
||||
resource.reset_password_token = params[:spree_user][:reset_password_token]
|
||||
set_flash_message(:error, :cannot_be_blank)
|
||||
render :edit
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
65
app/controllers/spree/user_registrations_controller.rb
Normal file
65
app/controllers/spree/user_registrations_controller.rb
Normal file
@@ -0,0 +1,65 @@
|
||||
module Spree
|
||||
class UserRegistrationsController < Devise::RegistrationsController
|
||||
helper 'spree/base', 'spree/store'
|
||||
|
||||
include Spree::Core::ControllerHelpers::Auth
|
||||
include Spree::Core::ControllerHelpers::Common
|
||||
include Spree::Core::ControllerHelpers::Order
|
||||
include Spree::Core::ControllerHelpers::SSL
|
||||
|
||||
ssl_required
|
||||
before_filter :check_permissions, only: [:edit, :update]
|
||||
skip_before_filter :require_no_authentication
|
||||
|
||||
# GET /resource/sign_up
|
||||
def new
|
||||
super
|
||||
@user = resource
|
||||
end
|
||||
|
||||
# POST /resource/sign_up
|
||||
def create
|
||||
@user = build_resource(params[:spree_user])
|
||||
if resource.save
|
||||
set_flash_message(:notice, :signed_up)
|
||||
sign_in(:spree_user, @user)
|
||||
session[:spree_user_signup] = true
|
||||
associate_user
|
||||
respond_with resource, location: after_sign_up_path_for(resource)
|
||||
else
|
||||
clean_up_passwords(resource)
|
||||
render :new
|
||||
end
|
||||
end
|
||||
|
||||
# GET /resource/edit
|
||||
def edit
|
||||
super
|
||||
end
|
||||
|
||||
# PUT /resource
|
||||
def update
|
||||
super
|
||||
end
|
||||
|
||||
# DELETE /resource
|
||||
def destroy
|
||||
super
|
||||
end
|
||||
|
||||
# GET /resource/cancel
|
||||
# Forces the session data which is usually expired after sign
|
||||
# in to be expired now. This is useful if the user wants to
|
||||
# cancel oauth signing in/up in the middle of the process,
|
||||
# removing all OAuth session data.
|
||||
def cancel
|
||||
super
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def check_permissions
|
||||
authorize!(:create, resource)
|
||||
end
|
||||
end
|
||||
end
|
||||
56
app/controllers/spree/user_sessions_controller.rb
Normal file
56
app/controllers/spree/user_sessions_controller.rb
Normal file
@@ -0,0 +1,56 @@
|
||||
module Spree
|
||||
class UserSessionsController < Devise::SessionsController
|
||||
helper 'spree/base', 'spree/store'
|
||||
|
||||
include Spree::Core::ControllerHelpers::Auth
|
||||
include Spree::Core::ControllerHelpers::Common
|
||||
include Spree::Core::ControllerHelpers::Order
|
||||
include Spree::Core::ControllerHelpers::SSL
|
||||
|
||||
ssl_required :new, :create, :destroy, :update
|
||||
ssl_allowed :login_bar
|
||||
|
||||
before_filter :set_checkout_redirect, only: :create
|
||||
|
||||
def create
|
||||
authenticate_spree_user!
|
||||
|
||||
if spree_user_signed_in?
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
flash[:success] = t('devise.success.logged_in_succesfully')
|
||||
redirect_back_or_default(after_sign_in_path_for(spree_current_user))
|
||||
}
|
||||
format.js {
|
||||
render json: { email: spree_current_user.login }, status: :ok
|
||||
}
|
||||
end
|
||||
else
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
flash.now[:error] = t('devise.failure.invalid')
|
||||
render :new
|
||||
}
|
||||
format.js {
|
||||
render json: { message: t('devise.failure.invalid') }, status: :unauthorized
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def nav_bar
|
||||
render partial: 'spree/shared/nav_bar'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def accurate_title
|
||||
Spree.t(:login)
|
||||
end
|
||||
|
||||
def redirect_back_or_default(default)
|
||||
redirect_to(session["spree_user_return_to"] || default)
|
||||
session["spree_user_return_to"] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,29 +0,0 @@
|
||||
Spree::UserSessionsController.class_eval do
|
||||
before_filter :set_checkout_redirect, only: :create
|
||||
|
||||
def create
|
||||
authenticate_spree_user!
|
||||
|
||||
if spree_user_signed_in?
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
flash[:success] = t('devise.success.logged_in_succesfully')
|
||||
redirect_back_or_default(after_sign_in_path_for(spree_current_user))
|
||||
}
|
||||
format.js {
|
||||
render json: { email: spree_current_user.login }, status: :ok
|
||||
}
|
||||
end
|
||||
else
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
flash.now[:error] = t('devise.failure.invalid')
|
||||
render :new
|
||||
}
|
||||
format.js {
|
||||
render json: { message: t('devise.failure.invalid') }, status: :unauthorized
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
74
app/controllers/spree/users_controller.rb
Normal file
74
app/controllers/spree/users_controller.rb
Normal file
@@ -0,0 +1,74 @@
|
||||
module Spree
|
||||
class UsersController < Spree::StoreController
|
||||
layout 'darkswarm'
|
||||
ssl_required
|
||||
skip_before_filter :set_current_order, only: :show
|
||||
prepend_before_filter :load_object, only: [:show, :edit, :update]
|
||||
prepend_before_filter :authorize_actions, only: :new
|
||||
|
||||
include Spree::Core::ControllerHelpers
|
||||
include I18nHelper
|
||||
|
||||
before_filter :set_locale
|
||||
before_filter :enable_embedded_shopfront
|
||||
|
||||
# Ignores invoice orders, only order where state: 'complete'
|
||||
def show
|
||||
@orders = @user.orders.where(state: 'complete').order('completed_at desc')
|
||||
@unconfirmed_email = spree_current_user.unconfirmed_email
|
||||
end
|
||||
|
||||
# Endpoint for queries to check if a user is already registered
|
||||
def registered_email
|
||||
user = Spree.user_class.find_by_email params[:email]
|
||||
render json: { registered: user.present? }
|
||||
end
|
||||
|
||||
def create
|
||||
@user = Spree::User.new(params[:user])
|
||||
if @user.save
|
||||
|
||||
if current_order
|
||||
session[:guest_token] = nil
|
||||
end
|
||||
|
||||
redirect_back_or_default(root_url)
|
||||
else
|
||||
render :new
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
if @user.update_attributes(params[:user])
|
||||
if params[:user][:password].present?
|
||||
# this logic needed b/c devise wants to log us out after password changes
|
||||
Spree::User.reset_password_by_token(params[:user])
|
||||
sign_in(@user, event: :authentication,
|
||||
bypass: true)
|
||||
end
|
||||
redirect_to spree.account_url, notice: Spree.t(:account_updated)
|
||||
else
|
||||
render :edit
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_object
|
||||
@user ||= spree_current_user
|
||||
if @user
|
||||
authorize! params[:action].to_sym, @user
|
||||
else
|
||||
redirect_to spree.login_path
|
||||
end
|
||||
end
|
||||
|
||||
def authorize_actions
|
||||
authorize! params[:action].to_sym, Spree::User.new
|
||||
end
|
||||
|
||||
def accurate_title
|
||||
Spree.t(:my_account)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,20 +0,0 @@
|
||||
Spree::UsersController.class_eval do
|
||||
layout 'darkswarm'
|
||||
include I18nHelper
|
||||
|
||||
before_filter :set_locale
|
||||
before_filter :enable_embedded_shopfront
|
||||
|
||||
# Override of spree_auth_devise default
|
||||
# Ignores invoice orders, only order where state: 'complete'
|
||||
def show
|
||||
@orders = @user.orders.where(state: 'complete').order('completed_at desc')
|
||||
@unconfirmed_email = spree_current_user.unconfirmed_email
|
||||
end
|
||||
|
||||
# Endpoint for queries to check if a user is already registered
|
||||
def registered_email
|
||||
user = Spree.user_class.find_by_email params[:email]
|
||||
render json: { registered: user.present? }
|
||||
end
|
||||
end
|
||||
@@ -61,6 +61,12 @@ module InjectionHelper
|
||||
inject_json_ams "currentOrder", current_order, Api::CurrentOrderSerializer, current_distributor: current_distributor, current_order_cycle: current_order_cycle
|
||||
end
|
||||
|
||||
def inject_current_order_cycle
|
||||
serializer = Api::OrderCycleSerializer.new(current_order_cycle)
|
||||
json = serializer.object.present? ? serializer.to_json : "{}"
|
||||
render partial: "json/injection_ams", locals: { name: "orderCycleData", json: json }
|
||||
end
|
||||
|
||||
def inject_available_shipping_methods
|
||||
inject_json_ams "shippingMethods", available_shipping_methods,
|
||||
Api::ShippingMethodSerializer, current_order: current_order
|
||||
@@ -111,8 +117,12 @@ module InjectionHelper
|
||||
inject_json_ams "savedCreditCards", data, Api::CreditCardSerializer
|
||||
end
|
||||
|
||||
def inject_json(name, partial, opts = {})
|
||||
render partial: "json/injection", locals: { name: name, partial: partial }.merge(opts)
|
||||
def inject_current_user
|
||||
inject_json_ams "user", spree_current_user, Api::UserSerializer
|
||||
end
|
||||
|
||||
def inject_rails_flash
|
||||
inject_json_ams "railsFlash", OpenStruct.new(flash.to_hash), Api::RailsFlashSerializer
|
||||
end
|
||||
|
||||
def inject_json_ams(name, data, serializer, opts = {})
|
||||
|
||||
@@ -18,6 +18,7 @@ module Spree
|
||||
klass = Spree::Order if klass == :bulk_order_management
|
||||
klass = EnterpriseGroup if klass == :group
|
||||
klass = VariantOverride if klass == :Inventory
|
||||
klass = ProductImport::ProductImporter if klass == :import
|
||||
klass = Spree::Admin::ReportsController if klass == :report
|
||||
klass
|
||||
end
|
||||
|
||||
@@ -59,7 +59,7 @@ class SubscriptionPlacementJob
|
||||
end
|
||||
|
||||
def move_to_completion(order)
|
||||
until order.completed? do order.next! end
|
||||
AdvanceOrderService.new(order).call!
|
||||
end
|
||||
|
||||
def unavailable_stock_lines_for(order)
|
||||
|
||||
47
app/mailers/spree/user_mailer.rb
Normal file
47
app/mailers/spree/user_mailer.rb
Normal file
@@ -0,0 +1,47 @@
|
||||
# This mailer is configured to be the Devise mailer
|
||||
# Some methods here override Devise::Mailer methods
|
||||
module Spree
|
||||
class UserMailer < BaseMailer
|
||||
include I18nHelper
|
||||
|
||||
# Overrides `Devise::Mailer.reset_password_instructions`
|
||||
def reset_password_instructions(user)
|
||||
recipient = user.respond_to?(:id) ? user : Spree.user_class.find(user)
|
||||
@edit_password_reset_url = spree.
|
||||
edit_spree_user_password_url(reset_password_token: recipient.reset_password_token)
|
||||
|
||||
mail(to: recipient.email, from: from_address,
|
||||
subject: Spree::Config[:site_name] + ' ' +
|
||||
I18n.t(:subject, scope: [:devise, :mailer, :reset_password_instructions]))
|
||||
end
|
||||
|
||||
# This is a OFN specific email, not from Devise::Mailer
|
||||
def signup_confirmation(user)
|
||||
@user = user
|
||||
I18n.with_locale valid_locale(@user) do
|
||||
mail(to: user.email, from: from_address,
|
||||
subject: t(:welcome_to) + Spree::Config[:site_name])
|
||||
end
|
||||
end
|
||||
|
||||
# Overrides `Devise::Mailer.confirmation_instructions`
|
||||
def confirmation_instructions(user, _opts)
|
||||
@user = user
|
||||
@instance = Spree::Config[:site_name]
|
||||
@contact = ContentConfig.footer_email
|
||||
|
||||
I18n.with_locale valid_locale(@user) do
|
||||
subject = t('spree.user_mailer.confirmation_instructions.subject')
|
||||
mail(to: confirmation_email_address,
|
||||
from: from_address,
|
||||
subject: subject)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def confirmation_email_address
|
||||
@user.pending_reconfirmation? ? @user.unconfirmed_email : @user.email
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,32 +0,0 @@
|
||||
Spree::UserMailer.class_eval do
|
||||
include I18nHelper
|
||||
|
||||
def signup_confirmation(user)
|
||||
@user = user
|
||||
I18n.with_locale valid_locale(@user) do
|
||||
mail(to: user.email, from: from_address,
|
||||
subject: t(:welcome_to) + Spree::Config[:site_name])
|
||||
end
|
||||
end
|
||||
|
||||
# Overriding `Spree::UserMailer.confirmation_instructions` which is
|
||||
# overriding `Devise::Mailer.confirmation_instructions`.
|
||||
def confirmation_instructions(user, _opts)
|
||||
@user = user
|
||||
@instance = Spree::Config[:site_name]
|
||||
@contact = ContentConfig.footer_email
|
||||
|
||||
I18n.with_locale valid_locale(@user) do
|
||||
subject = t('spree.user_mailer.confirmation_instructions.subject')
|
||||
mail(to: confirmation_email_address,
|
||||
from: from_address,
|
||||
subject: subject)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def confirmation_email_address
|
||||
@user.pending_reconfirmation? ? @user.unconfirmed_email : @user.email
|
||||
end
|
||||
end
|
||||
@@ -464,9 +464,11 @@ class Enterprise < ActiveRecord::Base
|
||||
self.permalink = Enterprise.find_available_permalink(name)
|
||||
end
|
||||
|
||||
# Touch distributors without them touching their distributors.
|
||||
# We avoid an infinite loop and don't need to touch the whole distributor tree.
|
||||
def touch_distributors
|
||||
Enterprise.distributing_products(supplied_products.select(:id)).
|
||||
where('enterprises.id != ?', id).
|
||||
find_each(&:touch)
|
||||
update_all(updated_at: Time.zone.now)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -25,8 +25,8 @@ class EnterpriseRelationship < ActiveRecord::Base
|
||||
where('parent_id IN (?) OR child_id IN (?)', enterprises, enterprises)
|
||||
}
|
||||
|
||||
scope :permitting, ->(enterprises) { where('child_id IN (?)', enterprises) }
|
||||
scope :permitted_by, ->(enterprises) { where('parent_id IN (?)', enterprises) }
|
||||
scope :permitting, ->(enterprise_ids) { where('child_id IN (?)', enterprise_ids) }
|
||||
scope :permitted_by, ->(enterprise_ids) { where('parent_id IN (?)', enterprise_ids) }
|
||||
|
||||
scope :with_permission, ->(permission) {
|
||||
joins(:permissions).
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
# Tells whether a particular feature is enabled or not
|
||||
class FeatureFlags
|
||||
# Constructor
|
||||
#
|
||||
# @param user [User]
|
||||
def initialize(user)
|
||||
@user = user
|
||||
end
|
||||
|
||||
# Checks whether product import is enabled for the specified user
|
||||
#
|
||||
# @return [Boolean]
|
||||
def product_import_enabled?
|
||||
user.superadmin?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :user
|
||||
end
|
||||
@@ -15,7 +15,7 @@ Spree::CreditCard.class_eval do
|
||||
belongs_to :user
|
||||
|
||||
after_create :ensure_single_default_card
|
||||
after_save :ensure_single_default_card, if: :is_default_changed?
|
||||
after_save :ensure_single_default_card, if: :default_card_needs_updating?
|
||||
|
||||
# Allows us to use a gateway_payment_profile_id to store Stripe Tokens
|
||||
# Should be able to remove once we reach Spree v2.2.0
|
||||
@@ -39,6 +39,10 @@ Spree::CreditCard.class_eval do
|
||||
!user.credit_cards.exists?(is_default: true)
|
||||
end
|
||||
|
||||
def default_card_needs_updating?
|
||||
is_default_changed? || gateway_customer_profile_id_changed?
|
||||
end
|
||||
|
||||
def ensure_single_default_card
|
||||
return unless user
|
||||
return unless is_default? || (reusable? && default_missing?)
|
||||
|
||||
@@ -118,7 +118,7 @@ Spree::Product.class_eval do
|
||||
|
||||
scope :stockable_by, lambda { |enterprise|
|
||||
return where('1=0') if enterprise.blank?
|
||||
permitted_producer_ids = EnterpriseRelationship.joins(:parent).permitting(enterprise)
|
||||
permitted_producer_ids = EnterpriseRelationship.joins(:parent).permitting(enterprise.id)
|
||||
.with_permission(:add_to_order_cycle).where(enterprises: { is_primary_producer: true }).pluck(:parent_id)
|
||||
return where('spree_products.supplier_id IN (?)', [enterprise.id] | permitted_producer_ids)
|
||||
}
|
||||
|
||||
@@ -17,9 +17,7 @@ class Spree::ProductSet < ModelSet
|
||||
# variant.update_attributes( { price: xx.x } )
|
||||
#
|
||||
def update_attributes(attributes)
|
||||
if attributes[:taxon_ids].present?
|
||||
attributes[:taxon_ids] = attributes[:taxon_ids].split(',')
|
||||
end
|
||||
split_taxon_ids!(attributes)
|
||||
|
||||
found_model = @collection.find do |model|
|
||||
model.id.to_s == attributes[:id].to_s && model.persisted?
|
||||
@@ -28,12 +26,20 @@ class Spree::ProductSet < ModelSet
|
||||
if found_model.nil?
|
||||
@klass.new(attributes).save unless @reject_if.andand.call(attributes)
|
||||
else
|
||||
update_product_only_attributes(found_model, attributes) &&
|
||||
update_product_variants(found_model, attributes) &&
|
||||
update_product_master(found_model, attributes)
|
||||
update_product(found_model, attributes)
|
||||
end
|
||||
end
|
||||
|
||||
def split_taxon_ids!(attributes)
|
||||
attributes[:taxon_ids] = attributes[:taxon_ids].split(',') if attributes[:taxon_ids].present?
|
||||
end
|
||||
|
||||
def update_product(found_model, attributes)
|
||||
update_product_only_attributes(found_model, attributes) &&
|
||||
update_product_variants(found_model, attributes) &&
|
||||
update_product_master(found_model, attributes)
|
||||
end
|
||||
|
||||
def update_product_only_attributes(product, attributes)
|
||||
variant_related_attrs = [:id, :variants_attributes, :master_attributes]
|
||||
product_related_attrs = attributes.except(*variant_related_attrs)
|
||||
@@ -90,8 +96,23 @@ class Spree::ProductSet < ModelSet
|
||||
|
||||
variant = product.variants.create(variant_attributes)
|
||||
|
||||
variant.on_demand = on_demand if on_demand.present?
|
||||
variant.on_hand = on_hand.to_i if on_hand.present?
|
||||
begin
|
||||
variant.on_demand = on_demand if on_demand.present?
|
||||
variant.on_hand = on_hand.to_i if on_hand.present?
|
||||
rescue StandardError => error
|
||||
notify_bugsnag(error, product, variant, variant_attributes)
|
||||
raise error
|
||||
end
|
||||
end
|
||||
|
||||
def notify_bugsnag(error, product, variant, variant_attributes)
|
||||
Bugsnag.notify(error) do |report|
|
||||
report.add_tab(:product, product.attributes)
|
||||
report.add_tab(:product_error, product.errors.first) unless product.valid?
|
||||
report.add_tab(:variant_attributes, variant_attributes)
|
||||
report.add_tab(:variant, variant.attributes)
|
||||
report.add_tab(:variant_error, variant.errors.first) unless variant.valid?
|
||||
end
|
||||
end
|
||||
|
||||
def collection_attributes=(attributes)
|
||||
|
||||
10
app/models/spree/stock_movement_decorator.rb
Normal file
10
app/models/spree/stock_movement_decorator.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
Spree::StockMovement.class_eval do
|
||||
after_save :refresh_products_cache
|
||||
|
||||
private
|
||||
|
||||
def refresh_products_cache
|
||||
return if stock_item.variant.blank?
|
||||
OpenFoodNetwork::ProductsCache.variant_changed stock_item.variant
|
||||
end
|
||||
end
|
||||
184
app/models/spree/user.rb
Normal file
184
app/models/spree/user.rb
Normal file
@@ -0,0 +1,184 @@
|
||||
module Spree
|
||||
class User < ActiveRecord::Base
|
||||
include Core::UserBanners
|
||||
|
||||
devise :database_authenticatable, :token_authenticatable, :registerable, :recoverable,
|
||||
:rememberable, :trackable, :validatable, :encryptable, encryptor: 'authlogic_sha512'
|
||||
|
||||
has_many :orders
|
||||
belongs_to :ship_address, foreign_key: 'ship_address_id', class_name: 'Spree::Address'
|
||||
belongs_to :bill_address, foreign_key: 'bill_address_id', class_name: 'Spree::Address'
|
||||
|
||||
before_validation :set_login
|
||||
before_destroy :check_completed_orders
|
||||
|
||||
# Setup accessible (or protected) attributes for your model
|
||||
attr_accessible :email, :password, :password_confirmation,
|
||||
:remember_me, :persistence_token, :login
|
||||
|
||||
users_table_name = User.table_name
|
||||
roles_table_name = Role.table_name
|
||||
|
||||
scope :admin, lambda { includes(:spree_roles).where("#{roles_table_name}.name" => "admin") }
|
||||
scope :registered, -> { where("#{users_table_name}.email NOT LIKE ?", "%@example.net") }
|
||||
|
||||
has_many :enterprise_roles, dependent: :destroy
|
||||
has_many :enterprises, through: :enterprise_roles
|
||||
has_many :owned_enterprises, class_name: 'Enterprise',
|
||||
foreign_key: :owner_id, inverse_of: :owner
|
||||
has_many :owned_groups, class_name: 'EnterpriseGroup',
|
||||
foreign_key: :owner_id, inverse_of: :owner
|
||||
has_many :customers
|
||||
has_many :credit_cards
|
||||
|
||||
accepts_nested_attributes_for :enterprise_roles, allow_destroy: true
|
||||
|
||||
accepts_nested_attributes_for :bill_address
|
||||
accepts_nested_attributes_for :ship_address
|
||||
|
||||
attr_accessible :enterprise_ids, :enterprise_roles_attributes, :enterprise_limit,
|
||||
:locale, :bill_address_attributes, :ship_address_attributes
|
||||
after_create :associate_customers
|
||||
|
||||
validate :limit_owned_enterprises
|
||||
|
||||
# We use the same options as Spree and add :confirmable
|
||||
devise :confirmable, reconfirmable: true
|
||||
# TODO: Later versions of devise have a dedicated after_confirmation callback, so use that
|
||||
after_update :welcome_after_confirm, if: lambda {
|
||||
confirmation_token_changed? && confirmation_token.nil?
|
||||
}
|
||||
|
||||
class DestroyWithOrdersError < StandardError; end
|
||||
|
||||
# Creates an anonymous user. An anonymous user is basically an auto-generated +User+ account
|
||||
# that is created for the customer behind the scenes and it's transparent to the customer.
|
||||
# All +Orders+ must have a +User+ so this is necessary when adding to the "cart" (an order)
|
||||
# and before the customer has a chance to provide an email or to register.
|
||||
def self.anonymous!
|
||||
token = User.generate_token(:persistence_token)
|
||||
User.create(email: "#{token}@example.net",
|
||||
password: token, password_confirmation: token, persistence_token: token)
|
||||
end
|
||||
|
||||
def self.admin_created?
|
||||
User.admin.count > 0
|
||||
end
|
||||
|
||||
def admin?
|
||||
has_spree_role?('admin')
|
||||
end
|
||||
|
||||
def anonymous?
|
||||
email =~ /@example.net$/ ? true : false
|
||||
end
|
||||
|
||||
def send_reset_password_instructions
|
||||
generate_reset_password_token!
|
||||
UserMailer.reset_password_instructions(id).deliver
|
||||
end
|
||||
# handle_asynchronously will define send_reset_password_instructions_with_delay.
|
||||
# If handle_asynchronously is called twice, we get an infinite job loop.
|
||||
handle_asynchronously :send_reset_password_instructions unless method_defined? :send_reset_password_instructions_with_delay
|
||||
|
||||
def known_users
|
||||
if admin?
|
||||
Spree::User.scoped
|
||||
else
|
||||
Spree::User
|
||||
.includes(:enterprises)
|
||||
.where("enterprises.id IN (SELECT enterprise_id FROM enterprise_roles WHERE user_id = ?)",
|
||||
id)
|
||||
end
|
||||
end
|
||||
|
||||
def build_enterprise_roles
|
||||
Enterprise.all.find_each do |enterprise|
|
||||
unless enterprise_roles.find_by_enterprise_id enterprise.id
|
||||
enterprise_roles.build(enterprise: enterprise)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def customer_of(enterprise)
|
||||
return nil unless enterprise
|
||||
customers.find_by_enterprise_id(enterprise)
|
||||
end
|
||||
|
||||
def welcome_after_confirm
|
||||
# Send welcome email if we are confirming an user's email
|
||||
# Note: this callback only runs on email confirmation
|
||||
return unless confirmed? && unconfirmed_email.nil? && !unconfirmed_email_changed?
|
||||
send_signup_confirmation
|
||||
end
|
||||
|
||||
def send_signup_confirmation
|
||||
Delayed::Job.enqueue ConfirmSignupJob.new(id)
|
||||
end
|
||||
|
||||
def associate_customers
|
||||
self.customers = Customer.where(email: email)
|
||||
end
|
||||
|
||||
def can_own_more_enterprises?
|
||||
owned_enterprises(:reload).size < enterprise_limit
|
||||
end
|
||||
|
||||
def default_card
|
||||
credit_cards.where(is_default: true).first
|
||||
end
|
||||
|
||||
# Checks whether the specified user is a superadmin, with full control of the
|
||||
# instance
|
||||
#
|
||||
# @return [Boolean]
|
||||
def superadmin?
|
||||
has_spree_role?('admin')
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def password_required?
|
||||
!persisted? || password.present? || password_confirmation.present?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_completed_orders
|
||||
raise DestroyWithOrdersError if orders.complete.present?
|
||||
end
|
||||
|
||||
def set_login
|
||||
# for now force login to be same as email, eventually we will make this configurable, etc.
|
||||
self.login ||= email if email
|
||||
end
|
||||
|
||||
# Generate a friendly string randomically to be used as token.
|
||||
def self.friendly_token
|
||||
SecureRandom.base64(15).tr('+/=', '-_ ').strip.delete("\n")
|
||||
end
|
||||
|
||||
# Generate a token by looping and ensuring does not already exist.
|
||||
def self.generate_token(column)
|
||||
loop do
|
||||
token = friendly_token
|
||||
break token unless find(:first, conditions: { column => token })
|
||||
end
|
||||
end
|
||||
|
||||
def limit_owned_enterprises
|
||||
return unless owned_enterprises.size > enterprise_limit
|
||||
errors.add(:owned_enterprises, I18n.t(:spree_user_enterprise_limit_error,
|
||||
email: email,
|
||||
enterprise_limit: enterprise_limit))
|
||||
end
|
||||
|
||||
def remove_payments_in_checkout(enterprises)
|
||||
enterprises.each do |enterprise|
|
||||
enterprise.distributed_orders.each do |order|
|
||||
order.payments.keep_if { |payment| payment.state != "checkout" }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,98 +0,0 @@
|
||||
Spree.user_class.class_eval do
|
||||
# handle_asynchronously will define send_reset_password_instructions_with_delay.
|
||||
# If handle_asynchronously is called twice, we get an infinite job loop.
|
||||
handle_asynchronously :send_reset_password_instructions unless method_defined? :send_reset_password_instructions_with_delay
|
||||
|
||||
has_many :enterprise_roles, dependent: :destroy
|
||||
has_many :enterprises, through: :enterprise_roles
|
||||
has_many :owned_enterprises, class_name: 'Enterprise', foreign_key: :owner_id, inverse_of: :owner
|
||||
has_many :owned_groups, class_name: 'EnterpriseGroup', foreign_key: :owner_id, inverse_of: :owner
|
||||
has_many :customers
|
||||
has_many :credit_cards
|
||||
|
||||
accepts_nested_attributes_for :enterprise_roles, allow_destroy: true
|
||||
|
||||
accepts_nested_attributes_for :bill_address
|
||||
accepts_nested_attributes_for :ship_address
|
||||
|
||||
attr_accessible :enterprise_ids, :enterprise_roles_attributes, :enterprise_limit, :locale, :bill_address_attributes, :ship_address_attributes
|
||||
after_create :associate_customers
|
||||
|
||||
validate :limit_owned_enterprises
|
||||
|
||||
# We use the same options as Spree and add :confirmable
|
||||
devise :confirmable, reconfirmable: true
|
||||
# TODO: Later versions of devise have a dedicated after_confirmation callback, so use that
|
||||
after_update :welcome_after_confirm, if: lambda { confirmation_token_changed? && confirmation_token.nil? }
|
||||
|
||||
def known_users
|
||||
if admin?
|
||||
Spree::User.scoped
|
||||
else
|
||||
Spree::User
|
||||
.includes(:enterprises)
|
||||
.where("enterprises.id IN (SELECT enterprise_id FROM enterprise_roles WHERE user_id = ?)", id)
|
||||
end
|
||||
end
|
||||
|
||||
def build_enterprise_roles
|
||||
Enterprise.all.find_each do |enterprise|
|
||||
unless enterprise_roles.find_by_enterprise_id enterprise.id
|
||||
enterprise_roles.build(enterprise: enterprise)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def customer_of(enterprise)
|
||||
return nil unless enterprise
|
||||
customers.find_by_enterprise_id(enterprise)
|
||||
end
|
||||
|
||||
def welcome_after_confirm
|
||||
# Send welcome email if we are confirming an user's email
|
||||
# Note: this callback only runs on email confirmation
|
||||
if confirmed? && unconfirmed_email.nil? && !unconfirmed_email_changed?
|
||||
send_signup_confirmation
|
||||
end
|
||||
end
|
||||
|
||||
def send_signup_confirmation
|
||||
Delayed::Job.enqueue ConfirmSignupJob.new(id)
|
||||
end
|
||||
|
||||
def associate_customers
|
||||
self.customers = Customer.where(email: email)
|
||||
end
|
||||
|
||||
def can_own_more_enterprises?
|
||||
owned_enterprises(:reload).size < enterprise_limit
|
||||
end
|
||||
|
||||
def default_card
|
||||
credit_cards.where(is_default: true).first
|
||||
end
|
||||
|
||||
# Checks whether the specified user is a superadmin, with full control of the
|
||||
# instance
|
||||
#
|
||||
# @return [Boolean]
|
||||
def superadmin?
|
||||
has_spree_role?('admin')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def limit_owned_enterprises
|
||||
if owned_enterprises.size > enterprise_limit
|
||||
errors.add(:owned_enterprises, I18n.t(:spree_user_enterprise_limit_error, email: email, enterprise_limit: enterprise_limit))
|
||||
end
|
||||
end
|
||||
|
||||
def remove_payments_in_checkout(enterprises)
|
||||
enterprises.each do |enterprise|
|
||||
enterprise.distributed_orders.each do |order|
|
||||
order.payments.keep_if { |payment| payment.state != "checkout" }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,6 +0,0 @@
|
||||
Deface::Override.new(virtual_path: "spree/admin/shared/_configuration_menu",
|
||||
name: "add_enterprise_fees_to_admin_configurations_menu",
|
||||
insert_bottom: "[data-hook='admin_configurations_sidebar_menu']",
|
||||
text: "<li><%= link_to I18n.t(:enterprise_fees), main_app.admin_enterprise_fees_path %></li>",
|
||||
partial: 'enterprise_fees/admin_configurations_menu',
|
||||
original: '8445a03cc903cacc832f395757ffcfaa7e99ca92')
|
||||
6
app/overrides/admin_tab.rb
Normal file
6
app/overrides/admin_tab.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
Deface::Override.new(virtual_path: "spree/layouts/admin",
|
||||
name: "user_admin_tabs",
|
||||
insert_bottom: "[data-hook='admin_tabs'], #admin_tabs[data-hook]",
|
||||
partial: "spree/admin/users_tab",
|
||||
disabled: false,
|
||||
original: '031652cf5a054796022506622082ab6d2693699f')
|
||||
5
app/overrides/auth_admin_login_navigation_bar.rb
Normal file
5
app/overrides/auth_admin_login_navigation_bar.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
Deface::Override.new(virtual_path: "spree/layouts/admin",
|
||||
name: "auth_admin_login_navigation_bar",
|
||||
insert_top: "[data-hook='admin_login_navigation_bar'], #admin_login_navigation_bar[data-hook]",
|
||||
partial: "spree/layouts/admin/login_nav",
|
||||
original: '841227d0aedf7909d62237d8778df99100087715')
|
||||
6
app/overrides/auth_shared_login_bar.rb
Normal file
6
app/overrides/auth_shared_login_bar.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
Deface::Override.new(virtual_path: "spree/shared/_nav_bar",
|
||||
name: "auth_shared_login_bar",
|
||||
insert_before: "li#search-bar",
|
||||
partial: "spree/shared/login_bar",
|
||||
disabled: false,
|
||||
original: 'eb3fa668cd98b6a1c75c36420ef1b238a1fc55ac')
|
||||
@@ -1,9 +0,0 @@
|
||||
/ replace_contents "[data-hook='adjustment_row']"
|
||||
|
||||
%td.align-center.created_at= pretty_time(adjustment.created_at)
|
||||
%td.align-center.label= adjustment.label
|
||||
%td.align-center.amount= adjustment.display_amount.to_html
|
||||
%td.align-center.included-tax= adjustment.display_included_tax.to_html
|
||||
%td.actions
|
||||
= link_to_edit adjustment, no_text: true
|
||||
= link_to_delete adjustment, no_text: true
|
||||
@@ -1,8 +0,0 @@
|
||||
/ replace_contents "[data-hook='adjustmment_head']"
|
||||
|
||||
%tr
|
||||
%th= "#{t('spree.date')}/#{t('spree.time')}"
|
||||
%th= t(:description)
|
||||
%th= t(:amount)
|
||||
%th= t(:included_tax)
|
||||
%th.actions
|
||||
@@ -1 +0,0 @@
|
||||
/ remove "tr:nth-child(4)"
|
||||
@@ -1,6 +0,0 @@
|
||||
/ replace_contents "[data-hook='admin_adjustment_form_fields']"
|
||||
|
||||
- if @adjustment.new_record?
|
||||
= render 'new_form', f: f
|
||||
- else
|
||||
= render 'edit_form', f: f
|
||||
@@ -1,11 +0,0 @@
|
||||
/ insert_after "fieldset.security"
|
||||
|
||||
%fieldset.embedded_shopfronts.no-border-bottom
|
||||
%legend{:align => "center"}= t('admin.shopfront_settings.embedded_shopfront_settings')
|
||||
.field
|
||||
= preference_field_tag(:enable_embedded_shopfronts, Spree::Config[:enable_embedded_shopfronts], type: Spree::Config.preference_type(:enable_embedded_shopfronts))
|
||||
= label_tag(:enable_embedded_shopfronts, t('admin.shopfront_settings.enable_embedded_shopfronts')) + tag(:br)
|
||||
.field
|
||||
= label_tag(:embedded_shopfronts_whitelist, t('admin.shopfront_settings.embedded_shopfronts_whitelist')) + tag(:br)
|
||||
= preference_field_tag(:embedded_shopfronts_whitelist, Spree::Config[:embedded_shopfronts_whitelist], type: Spree::Config.preference_type(:embedded_shopfronts_whitelist))
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
/ insert_after "fieldset.security"
|
||||
|
||||
%fieldset.legal.no-border-bottom
|
||||
%legend{:align => "center"}= t('.legal_settings')
|
||||
.field
|
||||
= label_tag(:footer_tos_url, t('.footer_tos_url')) + tag(:br)
|
||||
= preference_field_tag(:footer_tos_url, Spree::Config[:footer_tos_url], type: Spree::Config.preference_type(:footer_tos_url))
|
||||
.field
|
||||
= preference_field_tag(:enterprises_require_tos, Spree::Config[:enterprises_require_tos], :type => Spree::Config.preference_type(:enterprises_require_tos))
|
||||
= label_tag(:enterprises_require_tos, t('.enterprises_require_tos')) + tag(:br)
|
||||
.field
|
||||
= preference_field_tag(:cookies_consent_banner_toggle, Spree::Config[:cookies_consent_banner_toggle], :type => Spree::Config.preference_type(:cookies_consent_banner_toggle))
|
||||
= label_tag(:cookies_consent_banner_toggle, t('.cookies_consent_banner_toggle')) + tag(:br)
|
||||
.field
|
||||
= preference_field_tag(:cookies_policy_matomo_section, Spree::Config[:cookies_policy_matomo_section], :type => Spree::Config.preference_type(:cookies_policy_matomo_section))
|
||||
= label_tag(:cookies_policy_matomo_section, t('.cookies_policy_matomo_section')) + tag(:br)
|
||||
.field
|
||||
= preference_field_tag(:cookies_policy_ga_section, Spree::Config[:cookies_policy_ga_section], :type => Spree::Config.preference_type(:cookies_policy_ga_section))
|
||||
= label_tag(:cookies_policy_ga_section, t('.cookies_policy_ga_section')) + tag(:br)
|
||||
.field
|
||||
= label_tag(:privacy_policy_url, t('.privacy_policy_url')) + tag(:br)
|
||||
= preference_field_tag(:privacy_policy_url, Spree::Config[:privacy_policy_url], type: Spree::Config.preference_type(:privacy_policy_url))
|
||||
@@ -1,7 +0,0 @@
|
||||
/ insert_after "fieldset.currency"
|
||||
|
||||
%fieldset.number_localization.no-border-bottom
|
||||
%legend{:align => "center"}= t('admin.number_localization.number_localization_settings')
|
||||
.field
|
||||
= preference_field_tag(:enable_localized_number?, Spree::Config[:enable_localized_number?], type: Spree::Config.preference_type(:enable_localized_number?))
|
||||
= label_tag(:enable_localized_number?, t('admin.number_localization.enable_localized_number')) + tag(:br)
|
||||
@@ -1,11 +0,0 @@
|
||||
/ replace_contents '#styles_list'
|
||||
|
||||
- @styles.each_with_index do |(style_name, style_value), index|
|
||||
.field.three.columns
|
||||
= label_tag "attachment_styles[#{style_name}]", style_name
|
||||
%a.destroy_style{:alt => t(:destroy), :href => "#", :title => t(:destroy)}
|
||||
%i.icon-trash
|
||||
= text_field_tag "attachment_styles[#{style_name}][]", admin_image_settings_geometry_from_style(style_value), :class => 'fullwidth'
|
||||
%br/
|
||||
- current_format = admin_image_settings_format_from_style(style_value) || ''
|
||||
= select_tag "attachment_styles[#{style_name}][]", options_for_select(admin_image_settings_format_options, current_format), :class => 'fullwidth', :id => "attachment_styles_format_#{style_name}"
|
||||
@@ -1,2 +0,0 @@
|
||||
/ set_attributes "div[data-hook='customer_fields'] div.alpha"
|
||||
/ attributes({class: "fullwidth"})
|
||||
@@ -1 +0,0 @@
|
||||
remove "div[data-hook='customer_fields'] div.omega"
|
||||
@@ -1,6 +0,0 @@
|
||||
/ replace "erb[loud]:contains('hidden_field_tag :customer_search')"
|
||||
|
||||
- content_for :app_wrapper_attrs do
|
||||
= 'ng-app=admin.orders'
|
||||
|
||||
= hidden_field_tag :customer_search_override, nil, distributor_id: @order.distributor_id, :class => 'fullwidth title customer-search-override'
|
||||
@@ -1,6 +0,0 @@
|
||||
/ insert_after "code[erb-loud]:contains('button_link_to t(:edit)')"
|
||||
|
||||
%li.links-dropdown#links-dropdown{ links: order_links(@order).to_json }
|
||||
|
||||
:coffee
|
||||
angular.bootstrap(document.getElementById("links-dropdown"),['admin.dropdown'])
|
||||
@@ -1,6 +0,0 @@
|
||||
/ insert_after "[data-hook='admin_payment_methods_index_rows'] td:first-child"
|
||||
|
||||
%td.align-center
|
||||
- method.distributors.each do |distributor|
|
||||
= distributor.name
|
||||
%br/
|
||||
@@ -1,4 +0,0 @@
|
||||
/ insert_after "[data-hook='admin_payment_methods_index_headers'] th:first-child"
|
||||
|
||||
%th
|
||||
= t(:products_distributor)
|
||||
@@ -1,9 +0,0 @@
|
||||
/ replace_contents "table#listing_payment_methods colgroup"
|
||||
|
||||
%col{style: "width: 13%"}
|
||||
%col{style: "width: 14%"}
|
||||
%col{style: "width: 32%"}
|
||||
%col{style: "width: 14%"}
|
||||
%col{style: "width: 8%"}
|
||||
%col{style: "width: 8%"}
|
||||
%col{style: "width: 11%"}
|
||||
@@ -1 +0,0 @@
|
||||
remove "erb[loud]:contains(\"render :partial => 'spree/admin/shared/configuration_menu'\")"
|
||||
@@ -1,2 +0,0 @@
|
||||
/replace 'code[erb-loud]:contains("form_for @payment")'
|
||||
= form_for @payment, :url => admin_order_payments_path(@order), :html => {"ng-app" => "admin.payments", "ng-controller" => "PaymentCtrl"} do |f|
|
||||
@@ -1,3 +0,0 @@
|
||||
/ insert_before "fieldset.no-border-top"
|
||||
|
||||
%save-bar{ persist: "true" }
|
||||
@@ -1,2 +0,0 @@
|
||||
/replace 'code[erb-loud]:contains("button @order.cart?")'
|
||||
= button_tag t(:update), type: 'button', "ng-click" => "submitPayment()"
|
||||
@@ -1,7 +0,0 @@
|
||||
/ replace_contents "title"
|
||||
|
||||
- if content_for? :html_title
|
||||
= yield :html_title
|
||||
- else
|
||||
= t(controller.controller_name, :default => controller.controller_name.titleize)
|
||||
= " - OFN #{t(:administration)}"
|
||||
@@ -1,3 +0,0 @@
|
||||
/ replace_contents 'tr[data-hook="order_details_line_item_row"] td.price'
|
||||
|
||||
= item.single_display_amount
|
||||
@@ -1,3 +0,0 @@
|
||||
/ replace 'code[erb-loud]:contains(\'"(" + variant_options(item.variant) + ")"\')'
|
||||
|
||||
= "(#{item.full_name})"
|
||||
@@ -1,6 +0,0 @@
|
||||
/ insert_after "code[erb-silent]:contains('content_for :page_title')"
|
||||
|
||||
- if @order.bill_address.present?
|
||||
= @order.bill_address.firstname
|
||||
= @order.bill_address.lastname
|
||||
\-
|
||||
@@ -1,5 +0,0 @@
|
||||
/ insert_bottom "div[data-hook='admin_shipping_category_form_fields']"
|
||||
|
||||
%div.field.align-center{"data-hook" => "name"}
|
||||
= f.label :temperature_controlled, t(:temperature_controlled)
|
||||
= f.check_box :temperature_controlled
|
||||
@@ -1,5 +0,0 @@
|
||||
/ insert_after "[data-hook='category_row'] td:first-child"
|
||||
|
||||
%td.align-center
|
||||
= shipping_category.temperature_controlled ? t(:yes) : t(:no)
|
||||
%br/
|
||||
@@ -1,4 +0,0 @@
|
||||
/ insert_after "[data-hook='categories_header'] th:first-child"
|
||||
|
||||
%th
|
||||
= t(:temperature_controlled)
|
||||
@@ -1,2 +0,0 @@
|
||||
add_to_attributes '[data-hook="admin_variant_form_fields"]'
|
||||
attributes 'ng-app' => 'admin.products'
|
||||
@@ -1,25 +0,0 @@
|
||||
/ insert_top "[data-hook='admin_variant_form_fields']"
|
||||
|
||||
.field
|
||||
= f.label :display_name, t(:display_name)
|
||||
= f.text_field :display_name, class: "fullwidth"
|
||||
.field
|
||||
= f.label :display_as, t(:display_as)
|
||||
= f.text_field :display_as, class: "fullwidth"
|
||||
|
||||
- if product_has_variant_unit_option_type?(@product)
|
||||
- if @product.variant_unit != 'items'
|
||||
.field{"data-hook" => "unit_value", 'ng-controller' => 'variantUnitsCtrl'}
|
||||
= f.label :unit_value, "#{t('admin.'+@product.variant_unit)} ({{unitName(#{@product.variant_unit_scale}, '#{@product.variant_unit}')}})"
|
||||
= hidden_field_tag 'product_variant_unit_scale', @product.variant_unit_scale
|
||||
= text_field_tag :unit_value_human, nil, {class: "fullwidth", 'ng-model' => 'unit_value_human', 'ng-change' => 'updateValue()'}
|
||||
= f.text_field :unit_value, {hidden: true, 'ng-value' => 'unit_value'}
|
||||
|
||||
.field{"data-hook" => "unit_description"}
|
||||
= f.label :unit_description, t(:spree_admin_unit_description)
|
||||
= f.text_field :unit_description, class: "fullwidth", placeholder: t('admin.products.unit_name_placeholder')
|
||||
|
||||
:javascript
|
||||
angular.element(document.getElementById("new_variant")).ready(function() {
|
||||
angular.bootstrap(document.getElementById("new_variant"), ['admin.products']);
|
||||
});
|
||||
@@ -1,11 +0,0 @@
|
||||
/ insert_bottom "[data-hook='admin_variant_form_fields']"
|
||||
|
||||
- if Spree::Config[:track_inventory_levels]
|
||||
.field.checkbox
|
||||
%label
|
||||
= f.check_box :on_demand
|
||||
= t(:on_demand)
|
||||
.field
|
||||
= f.label :on_hand, t(:on_hand)
|
||||
.fullwidth
|
||||
= f.text_field :on_hand
|
||||
@@ -1,10 +0,0 @@
|
||||
/ replace "[data-hook='presentation']"
|
||||
|
||||
- unless variant_unit_option_type?(option_type)
|
||||
.field{"data-hook" => "presentation"}
|
||||
= label :new_variant, option_type.presentation
|
||||
- if @variant.new_record?
|
||||
= select(:new_variant, option_type.presentation, option_type.option_values.collect {|ov| [ ov.presentation, ov.id ] }, {}, {:class => 'select2 fullwidth'})
|
||||
- else
|
||||
- if opt = @variant.option_values.detect {|o| o.option_type == option_type }.try(:presentation)
|
||||
= text_field(:new_variant, option_type.presentation, :value => opt, :disabled => 'disabled', :class => 'fullwidth')
|
||||
@@ -1,33 +0,0 @@
|
||||
/ insert_bottom "[data-hook='admin_variant_form_fields']"
|
||||
:javascript
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
var on_demand = $('input#variant_on_demand');
|
||||
var on_hand = $('input#variant_on_hand');
|
||||
|
||||
disableOnHandIfOnDemand = function() {
|
||||
on_demand_checked = on_demand.attr('checked')
|
||||
if ( on_demand_checked == undefined )
|
||||
on_demand_checked = false;
|
||||
|
||||
on_hand.attr('disabled', on_demand_checked);
|
||||
if(on_demand_checked) {
|
||||
on_hand.attr('data-stock', on_hand.val());
|
||||
on_hand.val(t('admin.products.variants.infinity'));
|
||||
}
|
||||
}
|
||||
|
||||
disableOnHandIfOnDemand();
|
||||
|
||||
on_demand.change(function(){
|
||||
disableOnHandIfOnDemand();
|
||||
if(!this.checked) {
|
||||
if(on_hand.attr('data-stock') !== undefined) {
|
||||
on_hand.val(on_hand.attr('data-stock'));
|
||||
} else {
|
||||
on_hand.val("0");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,3 +0,0 @@
|
||||
/ insert_bottom "[data-hook='on_demand']"
|
||||
%div{'ofn-with-tip' => t('admin.products.variants.to_order_tip')}
|
||||
%a= t('admin.whats_this')
|
||||
@@ -1,14 +0,0 @@
|
||||
/ replace "[data-hook='admin_variant_form_additional_fields']"
|
||||
|
||||
.right.six.columns.omega.label-block{"data-hook" => "admin_variant_form_additional_fields"}
|
||||
- if @product.variant_unit != 'weight'
|
||||
.field{"data-hook" => 'weight'}
|
||||
= f.label 'weight', t('weight')+' (kg)'
|
||||
- value = number_with_precision(@variant.weight, :precision => 2)
|
||||
= f.text_field 'weight', :value => value, :class => 'fullwidth'
|
||||
|
||||
- [:height, :width, :depth].each do |field|
|
||||
.field{"data-hook" => field}
|
||||
= f.label field, t(field)
|
||||
- value = number_with_precision(@variant.send(field), :precision => 2)
|
||||
= f.text_field field, :value => value, :class => 'fullwidth'
|
||||
@@ -1,3 +0,0 @@
|
||||
/ replace "code[erb-loud]:contains('variant.options_text')"
|
||||
|
||||
= variant.full_name
|
||||
@@ -1,3 +0,0 @@
|
||||
/ insert_bottom "[data-hook='admin_footer_scripts']"
|
||||
|
||||
= render 'spree/shared/google_analytics'
|
||||
@@ -1,3 +0,0 @@
|
||||
/ insert_before "div#wrapper"
|
||||
|
||||
= admin_inject_currency_config
|
||||
@@ -1,2 +0,0 @@
|
||||
/ insert_bottom "[data-hook='admin_tabs'], #admin_tabs[data-hook]"
|
||||
= tab :customers, :url => main_app.admin_customers_path
|
||||
@@ -1,2 +0,0 @@
|
||||
/ insert_bottom "[data-hook='admin_tabs'], #admin_tabs[data-hook]"
|
||||
= tab :enterprises, :url => main_app.admin_enterprises_path
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user