Compare commits

...

311 Commits

Author SHA1 Message Date
Luis Ramos
6806035a45 Update all locales with the latest Transifex translations 2020-10-08 10:15:26 +01:00
Luis Ramos
b1dbf4fe0e Merge pull request #6147 from openfoodfoundation/transifex
Transifex
2020-10-08 10:13:00 +01:00
Luis Ramos
0829eaf0fb Merge pull request #6148 from openfoodfoundation/luisramos0-patch-1
Add break line troubleshooting to docker guide
2020-10-08 09:24:27 +01:00
Luis Ramos
da2e3c7cd1 Merge pull request #6144 from arku/fix/adjustment-metadata-spec
Fix adjustment metadata spec
2020-10-08 08:59:52 +01:00
Luis Ramos
d5f793f451 Add break line troubleshooting to docker guide 2020-10-08 08:40:14 +01:00
Transifex-Openfoodnetwork
8269665a7c Updating translations for config/locales/en_NZ.yml 2020-10-08 16:53:14 +11:00
Luis Ramos
1e7a3d7f46 Merge pull request #6123 from openfoodfoundation/mkllnk-patch-1
Create an initial Code of Conduct placeholder file
2020-10-07 23:36:59 +01:00
Luis Ramos
6c95444339 Merge pull request #6020 from andresgutgon/fix/admin-menu-in-multiple-lines
Fixed admin header buttons dropping multiple lines.
2020-10-07 21:24:48 +01:00
Luis Ramos
48ea804615 Merge pull request #6121 from cillian/fix-shop-variant-search
When searching for shop products check the variant :display_name and :display_as fields too
2020-10-07 21:22:46 +01:00
Luis Ramos
8626e7b433 Merge pull request #6094 from andrewpbrett/fix-inventory-import
Fix #6090 (Inventory import fails for products with units other than "g")
2020-10-07 21:21:40 +01:00
Luis Ramos
88b17372af Merge pull request #6131 from Snick555/issue-6118
Show product description in creation form after errors appeared
2020-10-07 21:21:13 +01:00
Luis Ramos
961e559a31 Merge pull request #6083 from luisramos0/shop_tabs_style
Make shop tabs black and capitalized in smaller screens
2020-10-07 14:39:23 +01:00
Pau Pérez Fabregat
85cee9e8cb Merge pull request #6091 from luisramos0/vat_rates_cache
Delete dead code brought from spree
2020-10-07 11:58:26 +02:00
Pau Pérez Fabregat
1e6fa1666c Merge pull request #6113 from openfoodfoundation/dependabot/bundler/knapsack-1.19.0
Bump knapsack from 1.18.0 to 1.19.0
2020-10-07 11:57:12 +02:00
Pau Pérez Fabregat
ce856750aa Merge pull request #6116 from openfoodfoundation/dependabot/bundler/ddtrace-0.41.0
Bump ddtrace from 0.40.0 to 0.41.0
2020-10-07 11:56:45 +02:00
Pau Pérez Fabregat
07e625ec32 Merge pull request #6104 from openfoodfoundation/dependabot/bundler/haml-5.2.0
Bump haml from 5.1.2 to 5.2.0
2020-10-07 11:56:12 +02:00
Arun Kumar Mohan
a20762a1f2 Fix adjustment metadata spec 2020-10-06 19:02:59 -05:00
Andy Brett
0edd341d46 add unit test for inventory import entry_validation 2020-10-06 10:17:30 -07:00
Luis Ramos
c31380cd1d Merge pull request #6132 from Matt-Yorkley/stripe-multiple-payments-spec
Stripe Tests: multiple attempted payments
2020-10-06 17:17:25 +01:00
Matt-Yorkley
0c109d6384 Merge pull request #6103 from openfoodfoundation/dependabot/bundler/dalli-2.7.11
Bump dalli from 2.7.10 to 2.7.11
2020-10-06 11:15:37 +02:00
Pau Pérez Fabregat
427d1aaeff Merge pull request #6079 from arku/perf/test-prof-setup
Set up test_prof gem
2020-10-06 10:30:43 +02:00
Matt-Yorkley
3b130327a5 DRY error_message variable used multiple times 2020-10-05 00:51:01 +01:00
Matt-Yorkley
ced5329835 Add Stripe spec for multiple attempted payments at checkout 2020-10-05 00:50:59 +01:00
dependabot-preview[bot]
ee6f0f7951 Bump ddtrace from 0.40.0 to 0.41.0
Bumps [ddtrace](https://github.com/DataDog/dd-trace-rb) from 0.40.0 to 0.41.0.
- [Release notes](https://github.com/DataDog/dd-trace-rb/releases)
- [Changelog](https://github.com/DataDog/dd-trace-rb/blob/master/CHANGELOG.md)
- [Commits](https://github.com/DataDog/dd-trace-rb/compare/v0.40.0...v0.41.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-04 19:18:47 +00:00
dependabot-preview[bot]
6149a79038 Bump knapsack from 1.18.0 to 1.19.0
Bumps [knapsack](https://github.com/ArturT/knapsack) from 1.18.0 to 1.19.0.
- [Release notes](https://github.com/ArturT/knapsack/releases)
- [Changelog](https://github.com/ArturT/knapsack/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ArturT/knapsack/compare/v1.18.0...v1.19.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-04 19:15:57 +00:00
ivoloshy
7321e4ef89 show product description in creation form after errors appeared 2020-10-04 20:44:57 +03:00
Matt-Yorkley
76def3a74f Merge pull request #6124 from luisramos0/stripe_specs
Add more checkout feature specs covering stripe SCA cases
2020-10-03 18:24:06 +02:00
Luis Ramos
a5309627b7 Fix a typo 2020-10-03 15:46:29 +01:00
Luis Ramos
80ea80f26e DRY stripe spec 2020-10-03 11:50:04 +01:00
Luis Ramos
14f5ecfe0b Add spec to cover StripeSCA extra auth with redirect and failed auth 2020-10-03 11:39:56 +01:00
Luis Ramos
df4ec67974 Add feature spec that covers stripe_sca redirect case 2020-10-03 11:09:24 +01:00
Maikel
4b1e1afa69 Create an initial Code of Conduct placeholder file 2020-10-03 08:48:15 +10:00
Luis Ramos
ef70c1fc5c Make helper more flexible and use it in a spec 2020-10-02 19:20:32 +01:00
Luis Ramos
83456f94e3 Simplify test by re-using helper stripe mock 2020-10-02 19:12:56 +01:00
Luis Ramos
ff9f374950 Merge pull request #6050 from Matt-Yorkley/stripe-checkout-spec
Stripe checkout spec
2020-10-02 18:57:22 +01:00
Cillian O'Ruanaidh
6c22ee43a7 When searching for shop products check the variant :display_name and :display_as fields too.
Fixes #5757
2020-10-02 16:05:48 +01:00
Luis Ramos
6a2e49b9e7 Update all locales with the latest Transifex translations 2020-10-02 12:54:45 +01:00
Luis Ramos
ab0ecfb203 Merge pull request #6106 from openfoodfoundation/transifex
Transifex
2020-10-02 12:46:56 +01:00
Luis Ramos
db2e760c4c Merge pull request #6120 from luisramos0/restart_checkout
Comment 2 broken specs until we manage to fix them
2020-10-02 12:39:04 +01:00
Luis Ramos
da82df39c2 Comment 2 broken specs until we manage to fix them 2020-10-02 11:59:38 +01:00
Luis Ramos
98fb60a5e0 Merge pull request #6110 from filipefurtad0/content_spec.rb
content_spec.rb improvement
2020-10-01 23:22:04 +01:00
Andy Brett
854916907e add feature spec for inventory import in kg 2020-10-01 13:27:57 -07:00
Matt-Yorkley
1cc950a4d9 DRY StripeHelper methods 2020-10-01 15:54:16 +01:00
Arun Kumar Mohan
4858f5fb80 Improve order specs' performance 2020-10-01 01:43:08 -05:00
Arun Kumar Mohan
350a3c0e1e Improve order checkout specs' performance 2020-10-01 01:43:08 -05:00
Arun Kumar Mohan
b850f10d2e Improve classification specs' performance 2020-10-01 01:43:08 -05:00
Arun Kumar Mohan
362ab8a605 Improve variant override specs' performance 2020-10-01 01:43:08 -05:00
Arun Kumar Mohan
f5985de802 Improve order cycle specs' performance 2020-10-01 01:43:08 -05:00
Arun Kumar Mohan
6c27ac5f99 Improve filter shipping methods tag rule specs' performance 2020-10-01 01:43:08 -05:00
Arun Kumar Mohan
bb38523767 Improve filter products tag rule specs' performance 2020-10-01 01:43:08 -05:00
Arun Kumar Mohan
e109ed6be7 Improve filter payment methods tag rule specs' performance 2020-10-01 01:43:08 -05:00
Arun Kumar Mohan
780f31f98e Improve filter order cycles tag rule specs' performance 2020-10-01 01:43:05 -05:00
François Turbelin
eda904337b Merge pull request #5810 from pacodelaluna/improve-dfc-standard-integration
Improve DFC Provider engine to support version 1.3
2020-09-30 11:13:03 +02:00
filipefurtad0
a85e500bb1 moves content_spec.rb into /configuration and adds an href string, incresing Redcarpet test coverage 2020-09-29 22:39:05 +01:00
Transifex-Openfoodnetwork
8480e16cac Updating translations for config/locales/tr.yml 2020-09-29 22:33:21 +10:00
Transifex-Openfoodnetwork
2eeba0483c Updating translations for config/locales/tr.yml 2020-09-29 22:30:18 +10:00
Transifex-Openfoodnetwork
e2ae566e88 Updating translations for config/locales/pl.yml 2020-09-29 22:08:01 +10:00
Transifex-Openfoodnetwork
01c6d5bc9c Updating translations for config/locales/ru.yml 2020-09-29 20:47:26 +10:00
Transifex-Openfoodnetwork
856ad24c6f Updating translations for config/locales/ru.yml 2020-09-29 20:44:21 +10:00
dependabot-preview[bot]
678e7acde0 Bump haml from 5.1.2 to 5.2.0
Bumps [haml](https://github.com/haml/haml) from 5.1.2 to 5.2.0.
- [Release notes](https://github.com/haml/haml/releases)
- [Changelog](https://github.com/haml/haml/blob/main/CHANGELOG.md)
- [Commits](https://github.com/haml/haml/compare/v5.1.2...v5.2.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-29 09:32:15 +00:00
dependabot-preview[bot]
4914a0d3a8 Bump dalli from 2.7.10 to 2.7.11
Bumps [dalli](https://github.com/petergoldstein/dalli) from 2.7.10 to 2.7.11.
- [Release notes](https://github.com/petergoldstein/dalli/releases)
- [Changelog](https://github.com/petergoldstein/dalli/blob/master/History.md)
- [Commits](https://github.com/petergoldstein/dalli/compare/v2.7.10...v2.7.11)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-29 09:29:14 +00:00
Pau Pérez Fabregat
e79187c1df Merge pull request #6097 from openfoodfoundation/transifex
Transifex
2020-09-29 09:22:59 +02:00
Matt-Yorkley
c518e7e0dd Extract Stripe credit card form filling 2020-09-28 19:59:26 +01:00
Matt-Yorkley
2babfa9a7b Add rejected card test 2020-09-28 19:55:52 +01:00
Transifex-Openfoodnetwork
c7d6b2782c Updating translations for config/locales/nb.yml 2020-09-28 22:29:05 +10:00
Transifex-Openfoodnetwork
3d71c2c0b8 Updating translations for config/locales/en_GB.yml 2020-09-28 21:31:02 +10:00
Pau Pérez Fabregat
807f91b0b8 Merge pull request #6093 from openfoodfoundation/RachL-patch-1
Hacktoberfest
2020-09-28 12:04:55 +02:00
Arun Kumar Mohan
6a722f2bbd Set up test-prof gem 2020-09-26 15:22:43 -05:00
Luis Ramos
d5ab3b47eb Merge pull request #6065 from arku/perf/address-specs
Replace `create` with `build_stubbed` in address model specs
2020-09-26 21:19:28 +01:00
Luis Ramos
0100963a39 Delete dead code brought from spree 2020-09-26 21:16:27 +01:00
Arun Kumar Mohan
06a3e55348 Replace create with build_stubbed in address model specs 2020-09-25 22:54:58 -05:00
Luis Ramos
bbef0bac5f Make font size 1em for larger screens 2020-09-25 21:28:22 +01:00
Rachel Arnould
dbe6c316f8 Change typo
"participating in" instead of "participating to"
2020-09-25 19:07:33 +02:00
Rachel Arnould
21eef7187b Hacktoberfest
A proposal for the banner on Hacktoberfest.
2020-09-25 18:13:00 +02:00
Andy Brett
4f942db0ba convert entry's unscaled_units to a float
This was coming in as a string, e.g. "1", so when we did "1" * 1000 it returned "11111111111111....." :)
2020-09-25 09:12:19 -07:00
Luis Ramos
9b5bd7bb1c Merge pull request #6066 from arku/perf/variant-override-specs
Replace `create` with `build_stubbed` in variant override model specs
2020-09-24 18:47:08 +01:00
Luis Ramos
c377e316d5 Merge pull request #6068 from arku/perf/coordinator-specs
Replace `create` with `build_stubbed` in coordinator model specs
2020-09-24 18:46:45 +01:00
Luis Ramos
aa74b58810 Merge pull request #6067 from arku/perf/tag-rule-specs
Remove unnecessary create call in tag rule model specs
2020-09-24 18:45:18 +01:00
Luis Ramos
8919adb6bf Merge pull request #6074 from arku/perf/shipping-rate-specs
Replace `create` with `build_stubbed` in shipping rate model specs
2020-09-24 18:42:30 +01:00
Luis Ramos
e04b85e900 Merge pull request #6078 from arku/perf/per-item-flexi-rate-specs
Replace `build` with `build_stubbed` in flexi rate and per item model specs
2020-09-24 18:41:29 +01:00
Luis Ramos
b8fae8e3a3 Merge pull request #6077 from arku/perf/calculator-price-sack-specs
Replace `build` with `build_stubbed` in price sack model specs
2020-09-24 18:41:19 +01:00
Luis Ramos
01fdee9dba Merge pull request #6076 from arku/perf/calculator-flat-percent-item-total-specs
Replace `build` with `build_stubbed` in flat percent item total specs
2020-09-24 18:40:55 +01:00
Luis Ramos
dfd54c1cbc Merge pull request #6075 from arku/perf/calculator-weight-specs
Replace `create` with `build_stubbed` in calculator weight model specs
2020-09-24 18:40:31 +01:00
Pau Pérez Fabregat
54a51a4995 Merge pull request #5988 from openfoodfoundation/dependabot/bundler/stripe-5.25.0
Bump stripe from 5.22.0 to 5.25.0
2020-09-23 21:14:32 +02:00
Pau Perez
37d113ed78 Update all locales with the latest Transifex translations 2020-09-23 21:09:49 +02:00
Pau Pérez Fabregat
8f6e527f8a Merge pull request #6044 from openfoodfoundation/transifex
Transifex
2020-09-23 21:06:44 +02:00
Pau Pérez Fabregat
0d259b217e Merge pull request #6017 from Matt-Yorkley/tidyup
Remove old code
2020-09-23 20:47:33 +02:00
Pau Pérez Fabregat
2e5b5eaac5 Merge pull request #6043 from andrewpbrett/imperial-units-product-import
Add oz and lb as allowed units in product import
2020-09-23 20:46:54 +02:00
Pau Pérez Fabregat
faaf391892 Merge pull request #6051 from luisramos0/russian
Adding the russian language to github
2020-09-23 20:43:22 +02:00
Transifex-Openfoodnetwork
feed9376dd Updating translations for config/locales/es.yml 2020-09-24 04:36:06 +10:00
Transifex-Openfoodnetwork
b829fea0c2 Updating translations for config/locales/ca.yml 2020-09-24 04:36:01 +10:00
Luis Ramos
a2610279d9 Merge pull request #5976 from luisramos0/address_form
Fix address state selector and "use billing address" checkbox in order customer details page
2020-09-23 12:42:37 +01:00
Luis Ramos
2234ea6f5a Make shop tabs black and capitalized 2020-09-22 16:59:42 +01:00
Matt-Yorkley
25a8c44c22 Merge pull request #6018 from Matt-Yorkley/tax-display
Tax display
2020-09-22 17:53:04 +02:00
Luis Ramos
7ebdc1d0da Merge pull request #6059 from andresgutgon/fix/sticky-search-bar-disapears-when-cart-is-open
Fix sticky search bar disappearing when cart is open.
2020-09-22 10:52:33 +01:00
Arun Kumar Mohan
bc77b8bcb2 Replace build with build_stubbed in per item model specs 2020-09-21 21:24:38 -05:00
Arun Kumar Mohan
38ab95a9a4 Replace build with build_stubbed in flexi rate model specs 2020-09-21 21:22:59 -05:00
Arun Kumar Mohan
698d8b35fa Replace build with build_stubbed in price sack model specs 2020-09-21 21:18:36 -05:00
Arun Kumar Mohan
a257a9e9d2 Replace build with build_stubbed in calculator weight model specs 2020-09-21 21:12:30 -05:00
Arun Kumar Mohan
231fbcd11a Replace build with build_stubbed in flat percent item total specs 2020-09-21 21:04:16 -05:00
Arun Kumar Mohan
c098ba0ce3 Replace create with build_stubbed in calculator weight model specs 2020-09-21 20:46:50 -05:00
Arun Kumar Mohan
f7a9cc63a7 Replace create with build_stubbed in shipping rate model specs 2020-09-21 20:37:35 -05:00
Luis Ramos
5c25d92354 Merge pull request #6069 from arku/perf/adjustment-metadata-specs
Replace `create` with `build` in adjustment metadata model specs
2020-09-21 12:22:24 +01:00
Arun Kumar Mohan
0aa5ee081e Replace create with build in adjustment metadata model specs 2020-09-21 01:54:46 -05:00
Arun Kumar Mohan
317618595c Replace create with build_stubbed in coordinator model specs 2020-09-21 01:47:19 -05:00
Arun Kumar Mohan
289fd09e20 Remove unnecessary create call in tag rule model specs 2020-09-21 01:09:14 -05:00
Arun Kumar Mohan
239b6e7577 Replace create with build_stubbed in variant override model specs 2020-09-21 00:45:35 -05:00
Matt-Yorkley
5bca561c4a Refactor Stripe request stubbing to helper 2020-09-20 17:06:03 +01:00
Transifex-Openfoodnetwork
82cf2afec9 Updating translations for config/locales/en_CA.yml 2020-09-20 23:27:52 +10:00
Transifex-Openfoodnetwork
8ea7614353 Updating translations for config/locales/fr_CA.yml 2020-09-20 23:25:11 +10:00
Luis Ramos
714bfafede Merge pull request #6037 from arku/fix/hash-diff-deprecation
Remove Hash#diff from cancan helper
2020-09-19 20:21:24 +01:00
Luis Ramos
8f98fb830a Merge pull request #6053 from jhsu802701/bundler_1_17_3
Upgraded the bundler version in the Dockerfile
2020-09-19 19:33:48 +01:00
Matt-Yorkley
6737270ab7 Rename partial 2020-09-19 15:49:14 +01:00
Matt-Yorkley
70bd2161ba Rename Stripe Connect factory for clarity 2020-09-19 12:55:31 +01:00
Matt-Yorkley
1d01fc955d Include StripeJS fixture and refactor to partial 2020-09-19 12:20:55 +01:00
Matt-Yorkley
4080e7daa4 Add comments in StripeJS mock 2020-09-19 12:20:55 +01:00
Matt-Yorkley
cca8f9faf6 Add missing behaviour in StripeJS mock 2020-09-19 12:20:55 +01:00
andresgutgon
636da229ad Fix sticky search bar disappearing when cart is open.
So I think the issue is that all the HTML is wrapped on an
`off-canvas-wrap` class that is used for doing the sidebar car open over
main content. The problem is that when this car sidebar is open body of
HTML overflow is changed to `overflow: hidden` and search bar use CSS
`position: sticky;` which doesn't work  when its parent has overflow
hidden. The issue was that `off-canvas-wrap` had an `overflow: inherit`
which means when body is set to overflow hidden this div inherits it and
break search bar position sticky when cart sidebar is opened. The
solution is to use `position: initial` which means use what a div has as
default value for `overflow` which I think it's `visible`. This class is
overriding the same class that comes from Foundation Framework that set
this div to be `overflow: hidden`. The override was added when [we added
search sticky](ff69389bb0)

More info about the problem with [position:sticky and its parent having
overflow hidden](https://css-tricks.com/dealing-with-overflow-and-position-sticky/) also info about [position initial vs inherit](https://stackoverflow.com/a/29661356)
2020-09-19 12:21:24 +02:00
andresgutgon
ef85ac3e27 Fixed admin header buttons dropping multiple lines. 2020-09-19 11:37:09 +02:00
Matt-Yorkley
368772dad2 Add another missing method to StripeJS mock
Our Angular code calls this method in some tests and expects a Promise object with a hash describing a payment method.
2020-09-19 00:39:39 +01:00
Matt-Yorkley
857f4e3a37 Add missing method to StripeJS mock
Our Angular code calls this method for interacting with live form validations and messages. We don't really need to use in tests, it just needs to exist otherwise the specs fail.
2020-09-19 00:39:39 +01:00
Matt-Yorkley
67d136548f Update form elements to more accurately reflect actual Stripe form
These attributes more closely reflect the actual form injected by Stripe. The additional attributes are also useful for selecting elements in tests
2020-09-19 00:39:39 +01:00
Matt-Yorkley
4c77c41533 Remove unused postal field from form 2020-09-19 00:39:39 +01:00
Matt-Yorkley
49bd9bd778 Import StripeJS mock from fake_stripe gem
This is the original from https://github.com/thoughtbot/fake_stripe/blob/v0.3.0/lib/fake_stripe/assets/v3.js
2020-09-19 00:39:39 +01:00
Matt-Yorkley
0ba3977422 Add new Stripe checkout spec 2020-09-19 00:39:32 +01:00
Matt-Yorkley
4ed34bb942 Add javascript debug option to test suite 2020-09-18 21:20:47 +01:00
Jason Hsu
560577827f Upgraded the bundler version in the Dockerfile to be consistent with that specified in Gemfile.lock 2020-09-18 15:07:44 -05:00
Luis Ramos
9c1a7c13dc Adding the russian language 2020-09-18 16:43:57 +01:00
Transifex-Openfoodnetwork
9cb7275250 Updating translations for config/locales/ar.yml 2020-09-18 19:49:55 +10:00
Transifex-Openfoodnetwork
3bf98e295d Updating translations for config/locales/en_FR.yml 2020-09-18 17:36:38 +10:00
Transifex-Openfoodnetwork
678e0be0a5 Updating translations for config/locales/fr.yml 2020-09-18 17:36:29 +10:00
Andy Brett
0ef4dec15e specs for product import using pounds and ounces 2020-09-17 09:34:22 -07:00
Transifex-Openfoodnetwork
880ef9cf4f Updating translations for config/locales/es.yml 2020-09-18 01:01:34 +10:00
Transifex-Openfoodnetwork
095633f21e Updating translations for config/locales/ca.yml 2020-09-18 00:59:40 +10:00
Pau Pérez Fabregat
3a894a1cdb Merge pull request #6002 from openfoodfoundation/dependabot/bundler/unicorn-5.7.0
Bump unicorn from 5.6.0 to 5.7.0
2020-09-17 16:57:16 +02:00
Transifex-Openfoodnetwork
ee862891c1 Updating translations for config/locales/en_FR.yml 2020-09-18 00:51:30 +10:00
Transifex-Openfoodnetwork
9dccb641c7 Updating translations for config/locales/fr.yml 2020-09-18 00:50:02 +10:00
Andy Brett
d1a87f7ba0 add oz and lb as allowed units in product import 2020-09-17 06:34:07 -07:00
Matt-Yorkley
77eaebc2a7 Merge pull request #5888 from andrewpbrett/imperial-auto-units
Allow US units on products/variants
2020-09-17 15:04:15 +02:00
Matt-Yorkley
3ececb04c5 Update all locales with the latest Transifex translations 2020-09-17 13:33:53 +01:00
Matt-Yorkley
0aa515101b Merge pull request #6015 from openfoodfoundation/transifex
Transifex
2020-09-17 14:31:41 +02:00
Luis Ramos
c6139a975a Merge pull request #6028 from openfoodfoundation/dependabot/bundler/webmock-3.9.1
Bump webmock from 3.8.3 to 3.9.1
2020-09-17 12:19:08 +01:00
Luis Ramos
212820b3da Merge pull request #5912 from luisramos0/tcs
Terms and Conditions - upload PDF in the Enterprise Business Details and read them on Checkout
2020-09-17 12:01:45 +01:00
Luis Ramos
f1358dfa9a Merge pull request #5722 from rioug/4206-back-from-Edit-Product-removed-filters-products-page
4206 back from edit product removed filters products page
2020-09-17 11:51:58 +01:00
Luis Ramos
f061545a92 Merge pull request #5995 from andresgutgon/fix/datetime-picker-ui-pick-the-right-translations-on-order-cycles
Fix date time picker translations on Order cycles screen
2020-09-17 11:50:37 +01:00
Luis Ramos
e99fdeb972 Merge pull request #5996 from andresgutgon/fix/iframe-shop-failing-because-jquery-is-not-loaded
Fix embedded shops failing javascript because jQuery is try to be accessed before being loaded
2020-09-17 11:32:08 +01:00
Transifex-Openfoodnetwork
875eb292be Updating translations for config/locales/ar.yml 2020-09-17 08:42:12 +10:00
Arun Kumar Mohan
08604ae8fd Remove Hash#diff usage from cancan helper 2020-09-16 12:14:37 -05:00
Luis Ramos
87d6a73e54 Merge pull request #5878 from luisramos0/shipping
[Bye bye Spree] Bring models shipping_method, shipping_rates, address and shipping_category from spree_core
2020-09-16 14:58:39 +01:00
Luis Ramos
f566c2127d Merge pull request #5924 from luisramos0/basic_spree_core
[Bye bye spree] Bring base_helper and log_entry from spree core
2020-09-16 14:57:41 +01:00
Transifex-Openfoodnetwork
2573e3b7c5 Updating translations for config/locales/es_CO.yml 2020-09-16 23:24:39 +10:00
Transifex-Openfoodnetwork
7fe876266e Updating translations for config/locales/es_CO.yml 2020-09-16 23:21:34 +10:00
Luis Ramos
8d5ed630d6 Merge pull request #6035 from arku/fix/adjustment-metadata-spec
Fix uninitialized constant error when running model specs
2020-09-16 10:15:46 +01:00
Luis Ramos
66d206ecb3 Merge pull request #6036 from arku/fix/pr-template
Fix typo in the PR template
2020-09-16 10:15:00 +01:00
Arun Kumar Mohan
fd0a7971e9 Fix typo in the PR template 2020-09-15 20:30:23 -05:00
Arun Kumar Mohan
ed3cb56c11 Fix uninitialized constant error when running model specs 2020-09-15 20:23:05 -05:00
Transifex-Openfoodnetwork
a367c3720c Updating translations for config/locales/en_US.yml 2020-09-16 10:21:50 +10:00
Luis Ramos
6eb43053e9 Merge pull request #5925 from luisramos0/spree_core_user
[Bye bye spree] Bring classes related to users to OFN
2020-09-15 17:13:27 +01:00
Pau Pérez Fabregat
7006b0af4c Merge pull request #6021 from Matt-Yorkley/concerns
Move concern to concerns directory
2020-09-15 17:45:24 +02:00
Transifex-Openfoodnetwork
d86b879972 Updating translations for config/locales/nb.yml 2020-09-15 20:46:33 +10:00
Transifex-Openfoodnetwork
fd339488e6 Updating translations for config/locales/es.yml 2020-09-15 20:38:08 +10:00
Transifex-Openfoodnetwork
b6f5eab6e1 Updating translations for config/locales/ca.yml 2020-09-15 20:37:51 +10:00
dependabot-preview[bot]
ced29c1f3d Bump webmock from 3.8.3 to 3.9.1
Bumps [webmock](https://github.com/bblimke/webmock) from 3.8.3 to 3.9.1.
- [Release notes](https://github.com/bblimke/webmock/releases)
- [Changelog](https://github.com/bblimke/webmock/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bblimke/webmock/compare/v3.8.3...v3.9.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-15 09:49:14 +00:00
Pau Pérez Fabregat
27ffe9edb2 Merge pull request #5971 from luisramos0/testing
Remove some old spree test helpers that are not needed
2020-09-15 09:13:20 +02:00
Luis Ramos
0d7b5cd32c Merge pull request #5868 from luisramos0/taxonomies
[Bye bye Spree] Bring models taxon and taxonomy from spree_core
2020-09-14 20:45:04 +01:00
Matt-Yorkley
276fea6942 Fix rubocop offenses 2020-09-14 15:14:16 +01:00
Matt-Yorkley
c45dcad975 Move concern to concerns directory 2020-09-14 13:23:21 +01:00
Transifex-Openfoodnetwork
f32d8e2678 Updating translations for config/locales/en_GB.yml 2020-09-13 04:29:16 +10:00
Transifex-Openfoodnetwork
a9a05debba Updating translations for config/locales/en_CA.yml 2020-09-13 02:30:11 +10:00
Matt-Yorkley
9481876595 Fix line_item tax sum in OrderTaxAdjustmentsFetcher 2020-09-12 15:41:29 +01:00
Matt-Yorkley
cdf4e88e21 Add failing spec for OrderTaxAdjustmentsFetcher with multiple line items 2020-09-12 15:40:06 +01:00
Matt-Yorkley
7ddc53bb5b Remove temporary debugging helpers added during the Rails 4 upgrade. 2020-09-12 12:25:43 +01:00
Transifex-Openfoodnetwork
b9f6dc6de5 Updating translations for config/locales/en_FR.yml 2020-09-12 00:25:49 +10:00
Transifex-Openfoodnetwork
811985cf0f Updating translations for config/locales/fr.yml 2020-09-12 00:25:36 +10:00
Luis Ramos
175b78b51f Merge pull request #5827 from jeduardo824/bug/remove-environment-column-when-user-is-not-super-admin
Bug/4592 - Hide Environment column on Payment Methods page when user is not admin
2020-09-11 10:47:10 +01:00
Luis Ramos
6f59158153 Remove useless TODOs 2020-09-10 17:36:25 +01:00
dependabot-preview[bot]
5eb64f431a Bump unicorn from 5.6.0 to 5.7.0
Bumps [unicorn](https://yhbt.net/unicorn/) from 5.6.0 to 5.7.0.

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-08 09:20:12 +00:00
andresgutgon
2297e20c78 Fix embedded shops failing javascript because jQuery is try to be
accessed before being loaded
Show we check for $.ready when jQuery is not downloaded yet in the
browser. The solution is to check if document is ready with plain DOM
javascript event `DOMContentLoaded`
2020-09-06 15:24:22 +02:00
andresgutgon
d1331ac78a Fix datetime picker translations on Order cycles screen
So the thing is we initialize jQuery plugin on `admin/util.js.erb` but
then we override those defaults on order_cycles.js.erb.coffe. Now both
plugin initializations use the same defaults. Also added 3 missing
translations for `Done`, `Now` and `Time` copies on that timepicker popover
2020-09-06 13:43:35 +02:00
Luis Ramos
5521b4bb04 Remove unused product filters 2020-09-05 16:43:27 +01:00
Luis Ramos
4183dda27e Fix long line 2020-09-05 16:43:27 +01:00
Luis Ramos
fcbb883244 Transpec taxon_spec 2020-09-05 16:43:27 +01:00
Luis Ramos
c35b330d25 Fix taxon_spec 2020-09-05 16:43:27 +01:00
Luis Ramos
57e74a4980 Fix rubocop issues 2020-09-05 16:43:27 +01:00
Luis Ramos
a1b64fe27b Rubocop auto-correct 2020-09-05 16:43:27 +01:00
Luis Ramos
49060892e8 Merge decorators into original files from spree_core 2020-09-05 16:43:27 +01:00
Luis Ramos
9175504bc1 Bring taxon, taxonomy and classification from spree_core 2020-09-05 16:43:27 +01:00
Eduardo
71876ca23a change spec to use new authentication helper and user factory 2020-09-04 08:48:16 -03:00
Eduardo
07e5f8ed8d fix typo on title of specs 2020-09-04 08:45:58 -03:00
Eduardo
11684dae65 hide environment on payment methods when user is not admin 2020-09-04 08:45:57 -03:00
Luis Ramos
e44efd3db2 Change test of attachment from present? to file? 2020-09-04 10:06:41 +01:00
dependabot-preview[bot]
cb61c83688 Bump stripe from 5.22.0 to 5.25.0
Bumps [stripe](https://github.com/stripe/stripe-ruby) from 5.22.0 to 5.25.0.
- [Release notes](https://github.com/stripe/stripe-ruby/releases)
- [Changelog](https://github.com/stripe/stripe-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-ruby/compare/v5.22.0...v5.25.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-03 17:49:28 +00:00
Luis Ramos
e413920335 Move both OptionValueNamer and VariantAndLineItemNaming to app/services/variant_units 2020-09-03 09:11:00 -07:00
Luis Ramos
83ae13d7c7 Extract method to make code easier to read 2020-09-03 09:11:00 -07:00
Luis Ramos
9204687e4d Fix rubocop issues 2020-09-03 09:11:00 -07:00
Luis Ramos
c6741dda36 Fix rubocop complexity issues by making code easier to read 2020-09-03 09:11:00 -07:00
Andy Brett
55f9fef2c3 denote that weight is in grams on the bulk order management page 2020-09-03 09:11:00 -07:00
Andy Brett
4bc3101f4d Add specs for shipping weight calculations using lbs and oz 2020-09-03 09:11:00 -07:00
Andy Brett
404d7bbc43 add test for options_text using g/lb 2020-09-03 09:11:00 -07:00
Andy Brett
55e448897f use fewer sigfigs for ounces; add spec to option_value_namer 2020-09-03 09:11:00 -07:00
Andy Brett
2fe9f4abc8 style updates for rubocop 2020-09-03 09:11:00 -07:00
Andy Brett
d7a8873ee9 return empty string for unitName if no scale matches 2020-09-03 09:11:00 -07:00
Andy Brett
a2993652c1 get only compatible scales in option_value_namer.js.coffee 2020-09-03 09:11:00 -07:00
Andy Brett
08e6e5a459 add compatibleUnitScales function and spec 2020-09-03 09:11:00 -07:00
Andy Brett
0018ef6eb4 refactor variant_unit_manager.coffee and add systems to scales 2020-09-03 09:11:00 -07:00
Andy Brett
9b9b6ded09 add each scales system in option_value_namer.rb 2020-09-03 09:11:00 -07:00
Andy Brett
e5e7e12a32 green tests for sorted scales 2020-09-03 09:11:00 -07:00
Andy Brett
2f216039ac update variantunitmanager test expectation 2020-09-03 09:11:00 -07:00
Andy Brett
e99799bca2 add ounces and round up for lbs 2020-09-03 09:11:00 -07:00
Zee Spencer
f5e300a5de Presenting a line item or variants options_text uses overriden values
This changes how we display the description of weight, but it doesn't
change the `Spree::OptionValue`s that are being created when someone
adds a product to their cart.

This takes us closer by making the UI look more correct; but it feels
odd compared to settiong the `Spree::OptionValue` to the correct
unit on creation.

But on the other hand, that could possibly make things worse for the
shipping calculation bits.
2020-09-03 09:10:59 -07:00
Zee Spencer
ae0b76e610 Support imperial units when scaling the unit value
We are pretty sure this is not the correct final implementation, but
we wanted to get some tests failing so we can start to fix them.
2020-09-03 09:10:59 -07:00
Zee Spencer
cb09c935dc WIP: Products may be created with pounds for their weight unit_converter
See: https://community.openfoodnetwork.org/t/hubs-managers-can-choose-the-adapted-weight-and-measure-units-for-their-shops-given-their-own-local-situation/1289/11

We're not entirely sure what needs to be changed in order for this to
accurately work with shipping and other parts of the eCommerce platform.

We are assuming that so long as we canonically store the weight scale
in grams, that the shipping calculation will be able to do what it needs
to. So if we put in values for "oz" as grams, we may not need to do
much else in order to let product(s) be sold by the pound (or ounce).

Next steps appear to be:

- [ ] When looking at an order as a customer, do we want to show pounds
      instead of grams? (See: http://localhost:3000/orders/R125684626)
- [ ] Compile a list of tests that are worth writing (because we have
      no confidence that we know what we are supposed to be doing in
      order for this feature to be "ready" to be used by people.)
- [ ] Write a test that demonstrates when we create a product with a
      variant in pound that the product's shipping weight is correctly
      calculated?
- [ ] Do we want to think about i18n?
2020-09-03 09:10:59 -07:00
François Turbelin
52d82d0a96 Use not found instead of 404 for spec descriptions 2020-09-03 00:59:21 +02:00
François Turbelin
d11d67561f Remove extra delegation in serializers 2020-09-03 00:58:54 +02:00
François Turbelin
d2c147109d Use Persons instead of People 2020-09-03 00:56:42 +02:00
François Turbelin
b60c1c9003 Dry current_enterprise emtod with enterprise_id_param_name 2020-09-03 00:50:23 +02:00
Luis Ramos
f28241cc5e Merge duplicate Spree::User#superadmin? into existing Spree::admin? 2020-09-02 22:41:42 +01:00
Luis Ramos
ebf4175662 MErge user class extensions into the User class 2020-09-02 22:41:39 +01:00
Luis Ramos
737fc699ed Fix rubocop issues 2020-09-02 22:40:46 +01:00
Luis Ramos
caf61e3a7e Run rubocop -a 2020-09-02 22:40:28 +01:00
Luis Ramos
dfa00a770a Bring user and ability related files from spree_core 2020-09-02 22:37:27 +01:00
François Turbelin
59fb2abc5d Fix inheritance issue with specs on Semaphore 2020-09-02 23:08:47 +02:00
François Turbelin
6508897e3d Introduce current_enterprise with memoization 2020-09-02 22:28:12 +02:00
François Turbelin
1baba5b61c Introduce current_user with memoization 2020-09-02 22:18:56 +02:00
François Turbelin
4f2b7094d0 Use before_action instead of before_filter 2020-09-02 21:48:13 +02:00
Luis Ramos
ffac38d934 Remove option to enter state_name for countries without states
Thisis not supported in OFN
2020-09-01 16:06:49 +01:00
Luis Ramos
5716ea8611 Fix rubocop issue 2020-09-01 15:55:46 +01:00
Luis Ramos
88d90a37e8 Run transpec 2020-09-01 15:53:18 +01:00
Luis Ramos
ed114f4c4c Fix rubocop issues 2020-09-01 15:52:36 +01:00
Luis Ramos
ffa0d202be Add states api endpoint to support existing code on the customer details page when user changes country 2020-09-01 15:46:22 +01:00
Luis Ramos
41d797489d Make onchange code simpler 2020-09-01 14:52:18 +01:00
Luis Ramos
46623242f7 Make use_billing checkbox work again, missign js code from spree 2020-09-01 14:28:45 +01:00
Luis Ramos
1a39a55009 Fix problem of converting from erb to haml 2020-09-01 14:09:06 +01:00
Luis Ramos
56fb09c006 Remove unused class 2020-09-01 14:03:20 +01:00
Luis Ramos
e4dee8a2fb Replace hash rockets 2020-09-01 13:57:57 +01:00
Luis Ramos
04f9c5ec5e Convert address form from erb to haml 2020-09-01 13:53:19 +01:00
Luis Ramos
8c322c1a0f Move shared address_form partial to the only place where it is used, order customer_details 2020-09-01 13:49:17 +01:00
Luis Ramos
865a4b3063 Fix base helper spec 2020-09-01 09:46:41 +01:00
Luis Ramos
b413f856a5 Clarify that it's a Spree issue number 2020-09-01 09:46:41 +01:00
Luis Ramos
2f93a06dd5 Run rubocop -a on files brought from spree_core 2020-09-01 09:46:41 +01:00
Luis Ramos
c151195e3a Merge decorator with original class and delete dead code 2020-09-01 09:46:41 +01:00
Luis Ramos
7ec00cf40a Bring base files from spree_core 2020-09-01 09:45:11 +01:00
Luis Ramos
208be3ede6 Fix rubocop issues 2020-08-31 20:00:08 +01:00
Luis Ramos
de061b4c54 Make it a keyword argument so it's easier to read 2020-08-31 18:47:24 +01:00
Luis Ramos
c7a5dd65cf Ensure all specs that change stripe_connect_enable set the value back to what it was before, which should be the default value false
This will speed up specs as it ensures the stripe is always disabled and its JS script is not loaded
2020-08-31 18:38:50 +01:00
Luis Ramos
d9a228e5ec Replace before and after hook with an around hook 2020-08-31 17:47:41 +01:00
Luis Ramos
8a75fe777c Refactor enterprises controller to reduce code duplication 2020-08-31 17:40:34 +01:00
Luis Ramos
66587ccc00 Allow user to remove terms and conditions file 2020-08-31 17:40:34 +01:00
Luis Ramos
24cdd0c467 Refactor enterprise controller to reduce code duplication 2020-08-31 17:40:34 +01:00
Luis Ramos
a3e9226878 Add option to remove existing terms and conditions file 2020-08-31 17:40:34 +01:00
Luis Ramos
0974c4b2ac Move enterprise images translations to the correct place using lazylookup on the server and to main js: namespace for js translations 2020-08-31 17:40:34 +01:00
Luis Ramos
5a10a2861e Reduce the size of the terms and conditions message on the checkout page 2020-08-31 17:40:34 +01:00
Luis Ramos
aedc12e0e3 Add top padding to terms file upload input in enterprises form 2020-08-31 17:40:34 +01:00
Luis Ramos
fc4cc65e07 Merge typography files in css admin 2020-08-31 17:40:34 +01:00
Luis Ramos
07cee32f04 Move enterprisse_console to pages/enterprise_form 2020-08-31 17:40:34 +01:00
Luis Ramos
42d5344179 Fix checkout spec by fixing wrong default value 2020-08-31 17:40:34 +01:00
Luis Ramos
12d18b2825 Add specs to checkout_spec to validate terms and conditions link 2020-08-31 17:40:34 +01:00
Luis Ramos
ad111e837e Add spec to test terms and conditions link on checkout page 2020-08-31 17:40:34 +01:00
Luis Ramos
746533d3f6 Improve spec titles 2020-08-31 17:40:34 +01:00
Luis Ramos
4ef4a58532 Merge two describe sections with same before method and call it what it is: guest checkout 2020-08-31 17:40:34 +01:00
Luis Ramos
685a5465f1 Simplify checkout stripe spec 2020-08-31 17:40:34 +01:00
Luis Ramos
70e9ef93bb Extract stripe spec from checkout spec so we can expand stripe tests in checkout 2020-08-31 17:40:34 +01:00
Luis Ramos
86ad31eb5c Reuse checkout form filling code from CheckoutHelper in checkout paypal spec 2020-08-31 17:40:34 +01:00
Luis Ramos
edfd0fd95c Move checkout helpers to checkout_helper 2020-08-31 17:40:34 +01:00
Luis Ramos
d1f5828d13 Rename checkout_workflow to checkout_helper 2020-08-31 17:40:34 +01:00
Luis Ramos
785f8ada4d Refactor checkout_spec by removing unnecessary initial describe section 2020-08-31 17:40:34 +01:00
Luis Ramos
b9511d4f07 Show terms and conditions on checkout if enterprise has an associated PDF file 2020-08-31 17:40:34 +01:00
Luis Ramos
16a475d8af Fix some rubocop issues 2020-08-31 17:40:34 +01:00
Luis Ramos
1a734aacf8 Allow user to upload terms and conditions PDF file to an enterprise 2020-08-31 17:40:34 +01:00
Luis Ramos
cfdfd82d9a Replace api controller test helpers with easier existing alternatives 2020-08-31 17:05:51 +01:00
Luis Ramos
b872bf49c5 Replace usage of helper method with a more simple approach 2020-08-31 16:56:48 +01:00
François Turbelin
d5800642e7 Map DFC SuppliedProduct with OFN Variant 2020-08-30 23:11:59 +02:00
Gaetan Riou
6564ea7b00 rename ProductFiltersService to ProductFiltersUrl 2020-08-21 12:13:16 +10:00
Gaetan Riou
f71013c514 rename query filter where it was missed, fix bulk_update_product spec 2020-08-21 11:46:36 +10:00
Gaetan Riou
44487af2c8 remove dead filter code 2020-08-21 11:40:48 +10:00
Gaetan Riou
c3279941f5 Remove product filter helper spec as it's not needed anymore 2020-08-21 10:42:02 +10:00
Gaetan Riou
7356d0fe77 move url filter functionality to service ProductFiltersService 2020-08-21 10:42:02 +10:00
Gaetan Riou
bba683469b add product filter parameters on the group buy options and search pages, so that the bulk import product page filters can be preserved 2020-08-21 10:39:43 +10:00
Gaetan Riou
c6e1f458cc add product filter parameters on the various product properties pages, so that the bulk import product page filters can be preserved 2020-08-21 10:39:43 +10:00
Gaetan Riou
9bc928fd48 update product variants feature test to use ulr helpers 2020-08-21 10:39:43 +10:00
Gaetan Riou
a6444e76a5 add product filter parameters on the various product image pages, so that the bulk import product page filters can be preserved 2020-08-21 10:29:07 +10:00
Gaetan Riou
9b26ff2fa4 move product filter helper to a service 2020-08-21 10:29:07 +10:00
Gaetan Riou
684ae2ca22 update product feature test to use ulr helpers 2020-08-21 10:29:07 +10:00
Gaetan Riou
459708dbc8 add product filter parameters on the various product variants pages, so that the bulk import product page filters can be preserved 2020-08-21 10:29:07 +10:00
Gaetan Riou
f75aaf0b45 extract product filter functionality to a helper 2020-08-21 10:19:53 +10:00
Gaetan Riou
1a186affcf refactor create and update to get rid of respond_override 2020-08-21 10:19:53 +10:00
Gaetan Riou
6e5c168d3b add filter parameters to link leading back to bulk import product page and preserve filter parameters when updating product 2020-08-21 10:19:53 +10:00
Gaetan Riou
39564e612f on admin product page, add selected filter to url and apply filter from url on page load 2020-08-21 10:19:53 +10:00
François Turbelin
c3cf08156d Add People controller 2020-08-13 11:49:45 +02:00
François Turbelin
8d4587506b Add SuppliedProducts controller 2020-08-13 11:46:48 +02:00
François Turbelin
99e905c768 Simplify enterprise check logic 2020-08-13 11:02:31 +02:00
François Turbelin
46d38930d9 Add some ajustements 2020-08-12 20:53:02 +02:00
François Turbelin
a4e8982351 Rename ProductsController into CatalogItemsController 2020-08-12 19:51:12 +02:00
François Turbelin
13e15f823e Add Read action for Enterprise and CatalogItem 2020-08-12 19:43:20 +02:00
François Turbelin
508ecd6bf7 Adjust with Rubocop suggestions 2020-08-12 13:46:23 +02:00
François Turbelin
d10fda6227 Put context inside serializer 2020-08-12 13:37:48 +02:00
François Turbelin
2a8268ca73 Use ActiveModelSerializer for DFC serialization 2020-08-12 13:37:01 +02:00
Luis Ramos
2d3578bb30 Fix address_spec 2020-08-07 14:05:36 +01:00
Luis Ramos
02f50774bb Run transpec 2020-08-07 12:47:44 +01:00
Luis Ramos
ff8735d7a4 Make new specs pass 2020-08-07 12:45:06 +01:00
Luis Ramos
51a499d5c9 Revert rubocop autocorrect so that spec keeps working 2020-08-07 10:45:15 +01:00
Luis Ramos
086c521a27 Fix easy rubocop issues 2020-08-07 10:28:41 +01:00
Luis Ramos
7cefdda579 Run rubocop autocorrect 2020-08-07 10:21:09 +01:00
Luis Ramos
ba859111de Merge decorators with original files brought from spree 2020-08-07 10:17:30 +01:00
Luis Ramos
fd9479f720 Bring modesl from spree_core 2020-08-07 10:06:08 +01:00
Luis Ramos
0c7a0e3e96 Bring modesl from spree_core 2020-08-07 10:06:04 +01:00
François Turbelin
8687e0199d Apply cosmetics 2020-08-05 08:20:14 +02:00
François Turbelin
2549d454ab Maintain specs 2020-07-23 09:28:32 +02:00
François Turbelin
645b4a9505 Use multiple serializers 2020-07-22 22:45:50 +02:00
François Turbelin
9f02ee3874 Use new serialization 2020-07-22 21:08:25 +02:00
François Turbelin
21fc14a9fe Use a better products list for catalog 2020-07-22 21:08:25 +02:00
249 changed files with 15986 additions and 2082 deletions

View File

@@ -20,6 +20,9 @@ plugins:
enabled: false
DeclarationOrder:
enabled: false
NestingDepth:
enabled: false
duplication:
enabled: true
exclude_patterns:

View File

@@ -38,6 +38,5 @@ Add the link or remove this section. -->
#### Documentation updates
<!-- Are their any wiki pages that need updating after merging this PR?
<!-- Are there any wiki pages that need updating after merging this PR?
List them here or remove this section. -->

3
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,3 @@
# Code of Conduct of the Open Food Network
**Welcome!** We are currently working on a Code of Conduct. You are welcome to contribute. We started this work at the Global Gathering 2020 and you find [notes of the initial session](https://community.openfoodnetwork.org/t/global-gathering-2020-day-5-a-code-of-conduct-for-ofn/2071/1) in the community forum. You can edit this file on Github to suggest new content. Alternatively, you can post in our [community forum](https://community.openfoodnetwork.org) or reach us on [Slack](https://openfoodnetwork.org/slack-invite).

View File

@@ -40,7 +40,7 @@ Push your changes to a branch on your fork:
## Submitting a Pull Request
Use the GitHub UI to submit a [new pull request][pr] against upstream/master. To increase the chances that your pull request is swiftly accepted please have a look at our guide to [making a great pull request][great-pr].
Use the GitHub UI to submit a [new pull request][pr] against upstream/master. To increase the chances that your pull request is swiftly accepted please have a look at our guide to [making a great pull request][great-pr].
TL;DR:
* Write tests

View File

@@ -60,3 +60,6 @@ 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.
You can find some useful tips and commands [here](https://github.com/openfoodfoundation/openfoodnetwork/wiki/Docker:-useful-tips-and-commands).
### Troubleshooting
If you are using Windows and having issues related to the ruby-build not finding a definition for the ruby version, you may need to follow these commands [here](https://stackoverflow.com/questions/2517190/how-do-i-force-git-to-use-lf-instead-of-crlf-under-windows/33424884#33424884) to fix your local git config related to line breaks.

View File

@@ -19,7 +19,7 @@ RUN git clone --depth 1 --branch v1.1.2 https://github.com/rbenv/rbenv.git ${RBE
echo 'eval "$(rbenv init -)"' >> /etc/profile.d/rbenv.sh && \
rbenv install $(cat .ruby-version) && \
rbenv global $(cat .ruby-version) && \
gem install bundler --version=1.17.2
gem install bundler --version=1.17.3
# Install Postgres
RUN sh -c "echo 'deb https://apt.postgresql.org/pub/repos/apt/ bionic-pgdg main' > /etc/apt/sources.list.d/pgdg.list" && \

View File

@@ -156,6 +156,7 @@ end
group :test do
gem 'simplecov', require: false
gem 'test-prof'
gem 'webmock'
# See spec/spec_helper.rb for instructions
# gem 'perftools.rb'

View File

@@ -64,6 +64,7 @@ PATH
remote: engines/dfc_provider
specs:
dfc_provider (0.0.1)
active_model_serializers (~> 0.8.4)
jwt (~> 2.2)
rspec (~> 3.9)
@@ -198,13 +199,13 @@ GEM
css_parser (1.7.1)
addressable
daemons (1.3.1)
dalli (2.7.10)
dalli (2.7.11)
database_cleaner (1.8.5)
db2fog (0.9.0)
activerecord (>= 3.2.0, < 5.0)
fog (~> 1.0)
rails (>= 3.2.0, < 5.0)
ddtrace (0.40.0)
ddtrace (0.41.0)
msgpack
debugger-linecache (1.2.0)
delayed_job (4.1.8)
@@ -411,7 +412,7 @@ GEM
get_process_mem (0.2.5)
ffi (~> 1.0)
gmaps4rails (2.1.2)
haml (5.1.2)
haml (5.2.0)
temple (>= 0.8.0)
tilt
hashdiff (1.0.1)
@@ -444,7 +445,7 @@ GEM
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
kgio (2.11.3)
knapsack (1.18.0)
knapsack (1.19.0)
rake
launchy (2.4.3)
addressable (~> 2.3)
@@ -509,7 +510,7 @@ GEM
pry-byebug (3.7.0)
byebug (~> 11.0)
pry (~> 0.10)
public_suffix (4.0.5)
public_suffix (4.0.6)
rack (1.5.5)
rack-mini-profiler (2.0.2)
rack (>= 1.2.0)
@@ -658,8 +659,9 @@ GEM
sprockets (>= 2.8, < 4.0)
state_machine (1.2.0)
stringex (1.5.1)
stripe (5.22.0)
stripe (5.25.0)
temple (0.8.2)
test-prof (0.7.5)
test-unit (3.3.6)
power_assert
thor (0.20.3)
@@ -671,7 +673,7 @@ GEM
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
unicode-display_width (1.7.0)
unicorn (5.6.0)
unicorn (5.7.0)
kgio (~> 2.6)
raindrops (~> 0.7)
unicorn-rails (2.2.1)
@@ -687,7 +689,7 @@ GEM
nokogiri (~> 1.6)
rubyzip (>= 1.3.0)
selenium-webdriver (>= 3.0, < 4.0)
webmock (3.8.3)
webmock (3.9.1)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
@@ -810,6 +812,7 @@ DEPENDENCIES
state_machine (= 1.2.0)
stringex (~> 1.5.1)
stripe
test-prof
test-unit (~> 3.3)
timecop
truncate_html (= 0.9.2)

View File

@@ -9,7 +9,7 @@ Supported by the Open Food Foundation and a network of global affiliates, we are
We're part of global movement - get involved!
* Join the conversation [on Slack][slack-invite]. Make sure you introduce yourself in the #general channel.
* Join the conversation [on Slack][slack-invite]. Make sure you introduce yourself in the #general channel and join #dev for all tech-related topics.
* Head to [https://openfoodnetwork.org](https://openfoodnetwork.org) for more information about the global OFN project.
* Check out the [User Guide](https://guide.openfoodnetwork.org/) for a list of features and tutorials.
* Join our [discussion forum](https://community.openfoodnetwork.org).
@@ -20,6 +20,11 @@ If you are interested in contributing to the OFN in any capacity, please introdu
Our [GETTING_STARTED](GETTING_STARTED.md) and [CONTRIBUTING](CONTRIBUTING.md) guides are the best place to start for developers looking to set up a development environment and make contributions to the codebase.
### Hacktoberfest :tada:
Are you participating in [Hacktoberfest](https://hacktoberfest.digitalocean.com/)? Go check out our [Welcome New Developers project board][welcome-dev]! We have curated all issues we consider to be a good starting point for new members of the community and categorized them by skills and level of complexity.
Have a look and pick the one you would prefer working on!
## Provisioning
If you're interested in provisioning a server, see [ofn-install][ofn-install] for the project's Ansible playbooks.
@@ -39,3 +44,4 @@ Copyright (c) 2012 - 2020 Open Food Foundation, released under the AGPL licence.
[contributor-guide]: https://ofn-user-guide.gitbook.io/ofn-contributor-guide/who-are-we
[ofn-install]: https://github.com/openfoodfoundation/ofn-install
[super-admin-guide]: https://ofn-user-guide.gitbook.io/ofn-super-admin-guide
[welcome-dev]: https://github.com/openfoodfoundation/openfoodnetwork/projects/27

View File

@@ -1,4 +1,4 @@
angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout, $filter, $http, $window, BulkProducts, DisplayProperties, DirtyProducts, VariantUnitManager, StatusMessage, producers, Taxons, Columns, tax_categories, RequestMonitor, SortOptions, ErrorsParser) ->
angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout, $filter, $http, $window, $location, BulkProducts, DisplayProperties, DirtyProducts, VariantUnitManager, StatusMessage, producers, Taxons, Columns, tax_categories, RequestMonitor, SortOptions, ErrorsParser, ProductFiltersUrl) ->
$scope.StatusMessage = StatusMessage
$scope.columns = Columns.columns
@@ -13,37 +13,29 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
{id: 100, name: t('js.admin.orders.index.per_page', results: 100)}
]
$scope.filterableColumns = [
{ name: t("label_producers"), db_column: "producer_name" },
{ name: t("name"), db_column: "name" }
]
$scope.filterTypes = [
{ name: t("equals"), predicate: "eq" },
{ name: t("contains"), predicate: "cont" }
]
$scope.optionTabs =
filters: { title: t("filter_products"), visible: false }
$scope.q = {
producerFilter: ""
categoryFilter: ""
importDateFilter: ""
query: ""
sorting: ""
}
$scope.producers = producers
$scope.taxons = Taxons.all
$scope.tax_categories = tax_categories
$scope.producerFilter = ""
$scope.categoryFilter = ""
$scope.importDateFilter = ""
$scope.page = 1
$scope.per_page = 15
$scope.products = BulkProducts.products
$scope.query = ""
$scope.DisplayProperties = DisplayProperties
$scope.sortOptions = SortOptions
$scope.initialise = ->
$scope.q = ProductFiltersUrl.loadFromUrl($location.search())
$scope.fetchProducts()
$scope.$watchCollection '[query, producerFilter, categoryFilter, importDateFilter, per_page]', ->
$scope.$watchCollection '[q.query, q.producerFilter, q.categoryFilter, q.importDateFilter, per_page]', ->
$scope.page = 1 # Reset page when changing filters for new search
$scope.changePage = (newPage) ->
@@ -53,25 +45,27 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
$scope.fetchProducts = ->
removeClearedValues()
params = {
'q[name_cont]': $scope.query,
'q[supplier_id_eq]': $scope.producerFilter,
'q[primary_taxon_id_eq]': $scope.categoryFilter,
'q[s]': $scope.sorting,
import_date: $scope.importDateFilter,
'q[name_cont]': $scope.q.query,
'q[supplier_id_eq]': $scope.q.producerFilter,
'q[primary_taxon_id_eq]': $scope.q.categoryFilter,
'q[s]': $scope.q.sorting,
import_date: $scope.q.importDateFilter,
page: $scope.page,
per_page: $scope.per_page
}
RequestMonitor.load(BulkProducts.fetch(params).$promise).then ->
# update url with the filters used
$location.search(ProductFiltersUrl.generate($scope.q))
$scope.resetProducts()
removeClearedValues = ->
delete $scope.producerFilter if $scope.producerFilter == "0"
delete $scope.categoryFilter if $scope.categoryFilter == "0"
delete $scope.importDateFilter if $scope.importDateFilter == "0"
delete $scope.q.producerFilter if $scope.q.producerFilter == "0"
delete $scope.q.categoryFilter if $scope.q.categoryFilter == "0"
delete $scope.q.importDateFilter if $scope.q.importDateFilter == "0"
$timeout ->
if $scope.showLatestImport
$scope.importDateFilter = $scope.importDates[1].id
$scope.q.importDateFilter = $scope.importDates[1].id
$scope.resetProducts = ->
DirtyProducts.clear()
@@ -101,10 +95,10 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
$scope.visibleTab = tab
$scope.resetSelectFilters = ->
$scope.query = ""
$scope.producerFilter = "0"
$scope.categoryFilter = "0"
$scope.importDateFilter = "0"
$scope.q.query = ""
$scope.q.producerFilter = "0"
$scope.q.categoryFilter = "0"
$scope.q.importDateFilter = "0"
$scope.fetchProducts()
$scope.$watch 'sortOptions', (sort) ->
@@ -122,8 +116,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
$scope.editWarn = (product, variant) ->
if confirm_unsaved_changes()
window.open(editProductUrl(product, variant), "_blank")
$window.location.href = ProductFiltersUrl.buildUrl(editProductUrl(product, variant), $scope.q)
$scope.toggleShowAllVariants = ->
showVariants = !DisplayProperties.showVariants 0
@@ -220,10 +213,10 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
data:
products: productsToSubmit
filters:
'q[name_cont]': $scope.query
'q[supplier_id_eq]': $scope.producerFilter
'q[primary_taxon_id_eq]': $scope.categoryFilter
import_date: $scope.importDateFilter
'q[name_cont]': $scope.q.query
'q[supplier_id_eq]': $scope.q.producerFilter
'q[primary_taxon_id_eq]': $scope.q.categoryFilter
import_date: $scope.q.importDateFilter
page: $scope.page
per_page: $scope.per_page
).success((data) ->

View File

@@ -5,5 +5,10 @@ angular.module("ofn.admin").directive "ofnSelect2MinSearch", ->
minimumResultsForSearch: attrs.ofnSelect2MinSearch
ngModel.$formatters.push (value) ->
if (value)
element.select2('val', value);
# select2 populates options with a value like "number:3" or "string:category" but
# select2('val', value) doesn't do the type conversion for us as one would expect
if isNaN(value)
element.select2('val', "string:#{value}")
else
element.select2('val', "number:#{value}")

View File

@@ -69,25 +69,24 @@ angular.module("admin.enterprises")
$scope.newUser = $scope.invite_errors = $scope.invite_success = null
$scope.removeLogo = ->
return unless confirm(t("admin.enterprises.remove_logo.immediate_removal_warning"))
Enterprises.removeLogo($scope.Enterprise).then (data) ->
$scope.Enterprise = angular.copy(data)
$scope.$emit("enterprise:updated", $scope.Enterprise)
StatusMessage.display("success", t("admin.enterprises.remove_logo.removed_successfully"))
, (response) ->
if response.data.error?
StatusMessage.display("failure", response.data.error)
$scope.performEnterpriseAction("removeLogo", "immediate_logo_removal_warning", "removed_logo_successfully")
$scope.removePromoImage = ->
return unless confirm(t("admin.enterprises.remove_promo_image.immediate_removal_warning"))
$scope.performEnterpriseAction("removePromoImage", "immediate_promo_image_removal_warning", "removed_promo_image_successfully")
Enterprises.removePromoImage($scope.Enterprise).then (data) ->
$scope.removeTermsAndConditions = ->
$scope.performEnterpriseAction("removeTermsAndConditions", "immediate_terms_and_conditions_removal_warning", "removed_terms_and_conditions_successfully")
$scope.performEnterpriseAction = (enterpriseActionName, warning_message_key, success_message_key) ->
return unless confirm($scope.translation(warning_message_key))
Enterprises[enterpriseActionName]($scope.Enterprise).then (data) ->
$scope.Enterprise = angular.copy(data)
$scope.$emit("enterprise:updated", $scope.Enterprise)
StatusMessage.display("success", t("admin.enterprises.remove_promo_image.removed_successfully"))
StatusMessage.display("success", $scope.translation(success_message_key))
, (response) ->
if response.data.error?
StatusMessage.display("failure", response.data.error)
$scope.translation = (key) ->
t('js.admin.enterprises.form.images.' + key)

View File

@@ -9,22 +9,19 @@ angular.module('admin.orderCycles', ['ngTagsInput', 'admin.indexUtils', 'admin.e
$timeout ->
# using $parse instead of scope[attrs.datetimepicker] for cases
# where attrs.datetimepicker is 'foo.bar.lol'
$(element).datetimepicker
dateFormat: 'yy-mm-dd'
timeFormat: 'HH:mm'
showOn: 'button'
controlType: 'select'
oneLine: true
buttonImage: "<%= asset_path 'datepicker/cal.gif' %>"
buttonImageOnly: true
stepMinute: 15
onSelect: (dateText, inst) ->
scope.$apply(->
element.val(dateText)
parsed = $parse(attrs.datetimepicker)
parsed.assign(scope, dateText)
)
$(element).datetimepicker(
Object.assign(
window.JQUERY_UI_DATETIME_PICKER_DEFAULTS,
{
onSelect: (dateText, inst) ->
scope.$apply(->
element.val(dateText)
parsed = $parse(attrs.datetimepicker)
parsed.assign(scope, dateText)
)
}
)
)
.directive 'ofnOnChange', ->
(scope, element, attrs) ->

View File

@@ -53,17 +53,18 @@ angular.module("admin.products").factory "OptionValueNamer", (VariantUnitManager
[value, unit_name]
scale_for_unit_value: ->
# Find the largest available unit where unit_value comes to >= 1 when expressed in it.
# If there is none available where this is true, use the smallest available unit.
unit = ([scale, unit_name] for scale, unit_name of VariantUnitManager.unitNames[@variant.product.variant_unit] when @variant.unit_value / scale >= 1).reduce (unit, [scale, unit_name]) ->
if (unit && scale > unit[0]) || !unit?
[scale, unit_name]
else
unit
, null
if !unit?
unit = ([scale, unit_name] for scale, unit_name of VariantUnitManager.unitNames[@variant.product.variant_unit]).reduce (unit, [scale, unit_name]) ->
if scale < unit[0] then [scale, unit_name] else unit
, [Infinity,""]
# Find the largest available and compatible unit where unit_value comes
# to >= 1 when expressed in it.
# If there is none available where this is true, use the smallest
# available unit.
product = @variant.product
scales = VariantUnitManager.compatibleUnitScales(product.variant_unit_scale, product.variant_unit)
variantUnitValue = @variant.unit_value
unit
# sets largestScale = last element in filtered scales array
[_, ..., largestScale] = (scales.filter (s) -> variantUnitValue / s >= 1)
if (largestScale)
[largestScale, VariantUnitManager.getUnitName(largestScale, product.variant_unit)]
else
[scales[0], VariantUnitManager.getUnitName(scales[0], product.variant_unit)]

View File

@@ -1,17 +1,35 @@
angular.module("admin.products").factory "VariantUnitManager", ->
class VariantUnitManager
@unitNames:
@units:
'weight':
1.0: 'g'
1000.0: 'kg'
1000000.0: 'T'
1.0:
name: 'g'
system: 'metric'
1000.0:
name: 'kg'
system: 'metric'
1000000.0:
name: 'T'
system: 'metric'
453.6:
name: 'lb'
system: 'imperial'
28.35:
name: 'oz'
system: 'imperial'
'volume':
0.001: 'mL'
1.0: 'L'
1000.0: 'kL'
0.001:
name: 'mL'
system: 'metric'
1.0:
name: 'L'
system: 'metric'
1000.0:
name: 'kL'
system: 'metric'
@variantUnitOptions: ->
options = for unit_type, scale_with_name of @unitNames
options = for unit_type, _ of @units
for scale in @unitScales(unit_type)
name = @getUnitName(scale, unit_type)
["#{I18n.t(unit_type)} (#{name})", "#{unit_type}_#{scale}"]
@@ -30,7 +48,16 @@ angular.module("admin.products").factory "VariantUnitManager", ->
unitScales[0]
@getUnitName: (scale, unitType) ->
@unitNames[unitType][scale]
if @units[unitType][scale]
@units[unitType][scale]['name']
else
''
@unitScales: (unitType) ->
(parseFloat(scale) for scale in Object.keys(@unitNames[unitType])).sort()
(parseFloat(scale) for scale in Object.keys(@units[unitType])).sort (a, b) ->
a - b
@compatibleUnitScales: (scale, unitType) ->
scaleSystem = @units[unitType][scale]['system']
(parseFloat(scale) for scale, scaleInfo of @units[unitType] when scaleInfo['system'] == scaleSystem).sort (a, b) ->
a - b

View File

@@ -14,4 +14,7 @@ angular.module("admin.resources").factory 'EnterpriseResource', ($resource) ->
'removePromoImage':
url: '/api/enterprises/:id/promo_image.json'
method: 'DELETE'
'removeTermsAndConditions':
url: '/api/enterprises/:id/terms_and_conditions.json'
method: 'DELETE'
})

View File

@@ -52,3 +52,4 @@ angular.module("admin.resources").factory 'Enterprises', ($q, EnterpriseResource
removeLogo: performActionOnEnterpriseResource(EnterpriseResource.removeLogo)
removePromoImage: performActionOnEnterpriseResource(EnterpriseResource.removePromoImage)
removeTermsAndConditions: performActionOnEnterpriseResource(EnterpriseResource.removeTermsAndConditions)

View File

@@ -0,0 +1,23 @@
angular.module("ofn.admin").factory "ProductFiltersUrl", ($httpParamSerializer) ->
new class ProductFiltersUrl
productFilters: ['producerFilter', 'categoryFilter', 'query', 'sorting', 'importDateFilter']
loadFromUrl: (filters) ->
loadedFilters = {}
for filter in @productFilters
loadedFilters[filter] = if filters[filter] then filters[filter] else ""
loadedFilters
generate: (ctrlFilters) ->
filters = {}
for filter in @productFilters
filters[filter] = ctrlFilters[filter] if ctrlFilters[filter]
filters
buildUrl: (baseUrl, ctrlFilters) ->
filterUrl = $httpParamSerializer(@generate(ctrlFilters))
filterUrl = "?#{filterUrl}" if filterUrl isnt ""
"#{baseUrl}#{filterUrl}"

View File

@@ -1,27 +1,17 @@
var update_state = function(region) {
var country = $('span#' + region + 'country .select2').select2('val');
var state_select = $('span#' + region + 'state select.select2');
var state_input = $('span#' + region + 'state input.state_name');
$.get(Spree.routes.states_search + "?country_id=" + country, function(data) {
var states = data["states"]
if (states.length > 0) {
state_select.html('');
var states_with_blank = [{name: '', id: ''}].concat(states);
$.each(states_with_blank, function(pos,state) {
var opt = $(document.createElement('option'))
.attr('value', state.id)
.html(state.name);
state_select.append(opt);
});
state_select.prop("disabled", false).show();
state_select.select2();
state_input.hide().prop("disabled", true);
} else {
state_input.prop("disabled", false).show();
state_select.select2('destroy').hide();
}
$.get(Spree.routes.states_search + "?country_id=" + country, function(states) {
state_select.html('');
var states_with_blank = [{name: '', id: ''}].concat(states);
$.each(states_with_blank, function(pos,state) {
var opt = $(document.createElement('option'))
.attr('value', state.id)
.html(state.name);
state_select.append(opt);
});
state_select.prop("disabled", false).show();
state_select.select2();
})
};

View File

@@ -0,0 +1,17 @@
$(document).ready(function() {
var order_use_billing_input = $('input#order_use_billing');
var order_use_billing = function () {
if (!order_use_billing_input.is(':checked')) {
$('#shipping').show();
} else {
$('#shipping').hide();
}
};
order_use_billing_input.click(function() {
order_use_billing();
});
order_use_billing();
});

View File

@@ -1,22 +1,30 @@
$(document).ready(function() {
$('.datetimepicker').datetimepicker({
dateFormat: 'yy-mm-dd',
timeFormat: 'HH:mm',
$(document).ready(function(){
window.JQUERY_UI_DATE_PICKER_DEFAULTS = {
dateFormat: Spree.translations.date_picker,
dayNames: Spree.translations.abbr_day_names,
dayNamesMin: Spree.translations.abbr_day_names,
monthNames: Spree.translations.month_names,
prevText: Spree.translations.previous,
nextText: Spree.translations.next,
showOn: 'button',
controlType: 'select',
oneLine: true,
showOn: 'button',
buttonImage: "<%= asset_path 'datepicker/cal.gif' %>",
buttonImageOnly: true,
stepMinute: 15
});
});
buttonImageOnly: true
}
$(document).ready(function(){
window.JQUERY_UI_DATETIME_PICKER_DEFAULTS = Object.assign(
{},
window.JQUERY_UI_DATE_PICKER_DEFAULTS,
{
currentText: Spree.translations.datetime_ui_current_text,
closeText: Spree.translations.datetime_ui_close_text,
timeText: Spree.translations.datetime_ui_time_text,
timeFormat: 'HH:mm',
controlType: 'select',
stepMinute: 15
}
);
$('.datetimepicker').datetimepicker(window.JQUERY_UI_DATETIME_PICKER_DEFAULTS);
$('a.close').click(function(event){
event.preventDefault();
$(this).parent().slideUp(250);

View File

@@ -68,7 +68,7 @@ Darkswarm.controller "ProductsCtrl", ($scope, $sce, $filter, $rootScope, Product
id: $scope.order_cycle.order_cycle_id,
page: page || $scope.page,
per_page: $scope.per_page,
'q[name_or_meta_keywords_or_supplier_name_cont]': $scope.query,
'q[name_or_meta_keywords_or_variants_display_as_or_variants_display_name_or_supplier_name_cont]': $scope.query,
'q[properties_id_or_supplier_properties_id_in_any][]': $scope.activeProperties,
'q[primary_taxon_id_in_any][]': $scope.activeTaxons
}

View File

@@ -1,3 +1,5 @@
@import 'shared/variables/layout';
// -------------------------------------------------------------
// Variables used in all other files
//--------------------------------------------------------------

View File

@@ -1,7 +1,9 @@
@import "variables";
@import "../variables";
span.unavailable, span.available {
span.unavailable,
span.available {
font-weight: bold;
i {
font-size: 150%;
}
@@ -13,4 +15,4 @@ span.available {
span.unavailable {
color: $warning-red;
}
}

View File

@@ -8,23 +8,61 @@
box-sizing: border-box;
}
// Helpers
.block-table {
display: table;
width: 100%;
.admin {
&__section-header {
padding: 15px 0;
background-color: very-light($color-3, 4);
border-bottom: 1px solid $color-border;
.table-cell {
display: table-cell;
vertical-align: middle;
padding: 0 10px;
&:first-child {
padding-left: 0;
width: 70%;
.ofn-drop-down {
border: 0;
background-color: $spree-blue;
color: $color-1;
float: none;
margin-left: 3px;
&:hover,
&.expanded {
border: 0;
color: $color-1;
}
}
&:last-child {
padding-right: 0;
width: 30%;
&__content {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
@media all and (min-width: $tablet_breakpoint) {
flex-wrap: nowrap;
}
}
&__title {
width: 100%;
margin-bottom: 10px;
@media all and (min-width: $tablet_breakpoint) {
margin-bottom: 0;
}
}
&__actions {
display: flex;
flex: 1 0 auto;
align-items: center;
list-style: none;
@media all and (min-width: $tablet_breakpoint) {
justify-content: flex-end;
}
> li {
display: flex;
margin-right: 10px;
&:empty {
display: none;
}
&:last-child {
margin-right: 0;
}
}
}
}
}
@@ -66,25 +104,6 @@
margin-top: 15px;
}
#content-header {
padding: 15px 0;
background-color: very-light($color-3, 4);
border-bottom: 1px solid $color-border;
.page-title {
font-size: 20px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.page-actions {
text-align: right;
form {
display: inline-block;
}
}
}
// Footer
//---------------------------------------------------
#footer {

View File

@@ -132,3 +132,25 @@ dl {
padding: 40px 0px;
color: lighten($color-body-text, 15);
}
.text-normal {
font-size: 1rem;
font-weight: 300;
}
.text-big {
font-size: 1.2rem;
font-weight: 300;
}
.text-red {
color: $warning-red;
}
input.text-big {
font-size: 1.1rem;
}
.pad-top {
padding-top: 1em;
}

View File

@@ -1,20 +0,0 @@
@import "variables";
.text-normal {
font-size: 1.0rem;
font-weight: 300;
}
.text-big {
font-size: 1.2rem;
font-weight: 300;
}
.text-red {
color: $warning-red;
}
input.text-big {
font-size: 1.1rem;
}

View File

@@ -212,7 +212,7 @@ nav.top-bar {
}
.off-canvas-wrap {
overflow: inherit;
overflow: initial;
}
.off-canvas-list li.language-switcher ul li {

View File

@@ -1,4 +1,5 @@
// Note this mixin file is used in ADMIN and FRONTEND
@import 'shared/variables/layout';
@import "branding";
@@ -258,15 +259,15 @@
@mixin breakpoint($point) {
@if $point == desktop {
@media all and (max-width: 1024px) { @content; }
@media all and (max-width: $desktop_breakpoint) { @content; }
}
@else if $point == tablet {
@media all and (max-width: 768px) { @content; }
@media all and (max-width: $tablet_breakpoint) { @content; }
}
@else if $point == phablet {
@media all and (max-width: 640px) { @content; }
@media all and (max-width: $phablet_breakpoint) { @content; }
}
@else if $point == mobile {
@media all and (max-width: 480px) { @content; }
@media all and (max-width: $mobile_breakpoint) { @content; }
}
}

View File

@@ -34,7 +34,7 @@
>a {
outline: none;
display: block;
color: $grey-500;
color: $black;
font-family: "Oswald", sans-serif;
}
@@ -42,9 +42,9 @@
@include headingFont;
background: transparent;
text-transform: uppercase;
text-transform: capitalize;
line-height: 1;
font-size: 0.875em;
font-size: 1em;
padding: 1em 2em;
border: none;
@@ -58,6 +58,7 @@
@include breakpoint(phablet) {
padding: 0.35em 0 0.65em 0;
font-size: 0.875em;
}
}

View File

@@ -0,0 +1,6 @@
// Breakpoints
$desktop_breakpoint: 1024px;
$tablet_breakpoint: 768px;
$phablet_breakpoint: 640px;
$mobile_breakpoint: 480px;

View File

@@ -33,12 +33,6 @@ module Api
use_renderers :json
check_authorization
# Temporary measure to help debugging strong_parameters
rescue_from ActiveModel::ForbiddenAttributesError, with: :print_params
def print_params
raise ActiveModel::ForbiddenAttributesError, params.to_s
end
def set_jsonp_format
return unless params[:callback] && request.get?

View File

@@ -75,7 +75,7 @@ module Api
end
def permitted_ransack_params
[:name_or_meta_keywords_or_supplier_name_cont,
[:name_or_meta_keywords_or_variants_display_as_or_variants_display_name_or_supplier_name_cont,
:properties_id_or_supplier_properties_id_in_any,
:primary_taxon_id_in_any]
end

View File

@@ -0,0 +1,44 @@
# frozen_string_literal: true
module Api
class StatesController < Api::BaseController
respond_to :json
skip_authorization_check
def index
render json: states, each_serializer: Api::StateSerializer, status: :ok
end
def show
@state = scope.find(params[:id])
render json: @state, serializer: Api::StateSerializer, status: :ok
end
private
def scope
if params[:country_id]
@country = Spree::Country.find(params[:country_id])
@country.states
else
Spree::State.all
end
end
def states
states = scope.ransack(params[:q]).result.
includes(:country).order('name ASC')
if pagination?
states = states.page(params[:page]).per(params[:per_page])
end
states
end
def pagination?
params[:page] || params[:per_page]
end
end
end

View File

@@ -0,0 +1,18 @@
# frozen_string_literal: true
module Api
class TermsAndConditionsController < Api::EnterpriseAttachmentController
private
def attachment_name
:terms_and_conditions
end
def enterprise_authorize_action
case action_name.to_sym
when :destroy
:remove_terms_and_conditions
end
end
end
end

View File

@@ -10,12 +10,6 @@ class ApplicationController < ActionController::Base
include EnterprisesHelper
include Spree::AuthenticationHelpers
# Temporary measure to help debugging strong_parameters
rescue_from ActiveModel::ForbiddenAttributesError, with: :print_params
def print_params
raise ActiveModel::ForbiddenAttributesError, params.to_s
end
def redirect_to(options = {}, response_status = {})
::Rails.logger.error("Redirected by #{begin
caller(1).first

View File

@@ -8,9 +8,55 @@ module Spree
before_action :load_data
create.before :set_viewable
update.before :set_viewable
destroy.before :destroy_before
def index
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
end
def new
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
render layout: !request.xhr?
end
def create
@url_filters = ::ProductFilters.new.extract(params)
set_viewable
@object.attributes = permitted_resource_params
if @object.save
flash[:success] = flash_message_for(@object, :successfully_created)
redirect_to admin_product_images_url(params[:product_id], @url_filters)
else
respond_with(@object)
end
end
def edit
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
end
def update
@url_filters = ::ProductFilters.new.extract(params)
set_viewable
if @object.update(permitted_resource_params)
flash[:success] = flash_message_for(@object, :successfully_updated)
redirect_to admin_product_images_url(params[:product_id], @url_filters)
else
respond_with(@object)
end
end
def destroy
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
destroy_before
if @object.destroy
flash[:success] = flash_message_for(@object, :successfully_removed)
end
redirect_to admin_product_images_url(params[:product_id], @url_filters)
end
private

View File

@@ -5,6 +5,20 @@ module Spree
before_action :find_properties
before_action :setup_property, only: [:index]
def index
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
end
def destroy
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
if @object.destroy
flash[:success] = flash_message_for(@object, :successfully_removed)
end
# if destroy fails it won't show any errors to the user
redirect_to admin_product_product_properties_url(params[:product_id], @url_filters)
end
private
def find_properties

View File

@@ -10,35 +10,32 @@ module Spree
include OrderCyclesHelper
include EnterprisesHelper
create.before :create_before
update.before :update_before
before_action :load_data
before_action :load_form_data, only: [:index, :new, :create, :edit, :update]
before_action :load_spree_api_key, only: [:index, :variant_overrides]
before_action :strip_new_properties, only: [:create, :update]
respond_override create: { html: {
success: lambda {
if params[:button] == "add_another"
redirect_to new_admin_product_path
else
redirect_to admin_products_path
end
},
failure: lambda {
render :new
}
} }
def new
@object.shipping_category = DefaultShippingCategory.find_or_create
super
end
def create
delete_stock_params_and_set_after do
super
if params[:product][:prototype_id].present?
@prototype = Spree::Prototype.find(params[:product][:prototype_id])
end
@object.attributes = permitted_resource_params
if @object.save
flash[:success] = flash_message_for(@object, :successfully_created)
if params[:button] == "add_another"
redirect_to new_admin_product_path
else
redirect_to admin_products_path
end
else
render :new
end
end
rescue Paperclip::Errors::NotIdentifiedByImageMagickError
invoke_callbacks(:create, :fails)
@@ -56,14 +53,24 @@ module Spree
@show_latest_import = params[:latest_import] || false
end
def update
original_supplier_id = @product.supplier_id
def edit
@url_filters = ::ProductFilters.new.extract(params)
end
def update
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
original_supplier_id = @product.supplier_id
delete_stock_params_and_set_after do
super
if original_supplier_id != @product.supplier_id
ExchangeVariantDeleter.new.delete(@product)
params[:product] ||= {} if params[:clear_product_properties]
if @object.update(permitted_resource_params)
if original_supplier_id != @product.supplier_id
ExchangeVariantDeleter.new.delete(@product)
end
flash[:success] = flash_message_for(@object, :successfully_updated)
end
redirect_to edit_admin_product_url(@object, @url_filters)
end
end
@@ -93,6 +100,14 @@ module Spree
redirect_to edit_admin_product_url(@new)
end
def group_buy_options
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
end
def seo
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
end
protected
def find_resource
@@ -135,19 +150,6 @@ module Spree
@collection
end
def create_before
return if params[:product][:prototype_id].blank?
@prototype = Spree::Prototype.find(params[:product][:prototype_id])
end
def update_before
# We only reset the product properties if we're receiving a post from the form on that tab
return unless params[:clear_product_properties]
params[:product] ||= {}
end
def product_includes
[{ variants: [:images, { option_values: :option_type }] },
{ master: [:images, :default_price] }]

View File

@@ -3,9 +3,6 @@ module Spree
class TaxRatesController < ResourceController
before_action :load_data
update.after :update_after
create.after :create_after
private
def load_data
@@ -14,14 +11,6 @@ module Spree
@calculators = TaxRate.calculators.sort_by(&:name)
end
def update_after
Rails.cache.delete('vat_rates')
end
def create_after
Rails.cache.delete('vat_rates')
end
def permitted_resource_params
params.require(:tax_rate).permit(
:name, :amount, :included_in_price, :zone_id,

View File

@@ -4,14 +4,46 @@ module Spree
module Admin
class VariantsController < ResourceController
helper 'spree/products'
belongs_to 'spree/product', find_by: :permalink
new_action.before :new_before
def index
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
end
def edit
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
end
def update
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
if @object.update(permitted_resource_params)
flash[:success] = flash_message_for(@object, :successfully_updated)
redirect_to admin_product_variants_url(params[:product_id], @url_filters)
else
redirect_to edit_admin_product_variant_url(params[:product_id], @object, @url_filters)
end
end
def new
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
end
def create
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
on_demand = params[:variant].delete(:on_demand)
on_hand = params[:variant].delete(:on_hand)
super
@object.attributes = permitted_resource_params
if @object.save
flash[:success] = flash_message_for(@object, :successfully_created)
redirect_to admin_product_variants_url(params[:product_id], @url_filters)
else
redirect_to new_admin_product_variant_url(params[:product_id], @url_filters)
end
return unless @object.present? && @object.valid?
@@ -26,6 +58,8 @@ module Spree
end
def destroy
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
@variant = Spree::Variant.find(params[:id])
flash[:success] = if VariantDeleter.new.delete(@variant)
Spree.t('notice_messages.variant_deleted')
@@ -33,9 +67,7 @@ module Spree
Spree.t('notice_messages.variant_not_deleted')
end
respond_with(@variant) do |format|
format.html { redirect_to admin_product_variants_url(params[:product_id]) }
end
redirect_to admin_product_variants_url(params[:product_id], @url_filters)
end
protected

View File

@@ -1,12 +1,7 @@
# frozen_string_literal: true
module Spree
module BaseHelper
# human readable list of variant options
# Override: Do not show out of stock text
def variant_options(variant, _options = {})
variant.options_text
end
# Overriden to eager-load :states
def available_countries
checkout_zone = Zone.find_by(name: Spree::Config[:checkout_zone])
@@ -21,5 +16,10 @@ module Spree
country
end.sort { |a, b| a.name <=> b.name }
end
def pretty_time(time)
[I18n.l(time.to_date, format: :long),
time.strftime("%l:%M %p")].join(" ")
end
end
end

View File

@@ -0,0 +1,19 @@
# frozen_string_literal: true
require 'active_support/concern'
# This concern is used to duplicate the associations distributors and distributor_ids
# across payment method and gateway
# this fixes the inheritance problem https://github.com/openfoodfoundation/openfoodnetwork/issues/2781
module PaymentMethodDistributors
extend ActiveSupport::Concern
def self.included(base)
base.class_eval do
has_and_belongs_to_many :distributors, join_table: 'distributors_payment_methods',
class_name: 'Enterprise',
foreign_key: 'payment_method_id',
association_foreign_key: 'distributor_id'
end
end
end

View File

@@ -12,10 +12,7 @@ class Enterprise < ActiveRecord::Base
preference :shopfront_order_cycle_order, :string, default: "orders_close_at"
preference :show_customer_names_to_suppliers, :boolean, default: false
# This is hopefully a temporary measure, pending the arrival of multiple named inventories
# for shops. We need this here to allow hubs to restrict visible variants to only those in
# their inventory if they so choose
# TODO: delegate this to a separate model instead of abusing Preferences.
# Allow hubs to restrict visible variants to only those in their inventory
preference :product_selection_from_inventory_only, :boolean, default: false
has_paper_trail only: [:owner_id, :sells], on: [:update]
@@ -78,10 +75,16 @@ class Enterprise < ActiveRecord::Base
},
url: '/images/enterprises/promo_images/:id/:style/:basename.:extension',
path: 'public/images/enterprises/promo_images/:id/:style/:basename.:extension'
validates_attachment_content_type :logo, content_type: %r{\Aimage/.*\Z}
validates_attachment_content_type :promo_image, content_type: %r{\Aimage/.*\Z}
has_attached_file :terms_and_conditions,
url: '/files/enterprises/terms_and_conditions/:id/:basename.:extension',
path: 'public/files/enterprises/terms_and_conditions/:id/:basename.:extension'
validates_attachment_content_type :terms_and_conditions,
content_type: "application/pdf",
message: I18n.t(:enterprise_terms_and_conditions_type_error)
include Spree::Core::S3Support
supports_s3 :logo
supports_s3 :promo_image

View File

@@ -159,7 +159,7 @@ module ProductImport
end
def unit_fields_validation(entry)
unit_types = ['g', 'kg', 't', 'ml', 'l', 'kl', '']
unit_types = ['g', 'oz', 'lb', 'kg', 't', 'ml', 'l', 'kl', '']
unless entry.units&.present?
mark_as_invalid(entry, attribute: 'units',
@@ -253,7 +253,7 @@ module ProductImport
products.flat_map(&:variants).each do |existing_variant|
unit_scale = existing_variant.product.variant_unit_scale
unscaled_units = entry.unscaled_units || 0
unscaled_units = entry.unscaled_units.to_f || 0
entry.unit_value = unscaled_units * unit_scale unless unit_scale.nil?
if entry_matches_existing_variant?(entry, existing_variant)

View File

@@ -32,6 +32,8 @@ module ProductImport
{
'g' => { scale: 1, unit: 'weight' },
'kg' => { scale: 1000, unit: 'weight' },
'oz' => { scale: 28.35, unit: 'weight' },
'lb' => { scale: 453.6, unit: 'weight' },
't' => { scale: 1_000_000, unit: 'weight' },
'ml' => { scale: 0.001, unit: 'volume' },
'l' => { scale: 1, unit: 'volume' },

View File

@@ -97,7 +97,9 @@ class AbilityDecorator
end
can [:admin, :index, :create], Enterprise
can [:read, :edit, :update, :remove_logo, :remove_promo_image, :bulk_update, :resend_confirmation], Enterprise do |enterprise|
can [:read, :edit, :update,
:remove_logo, :remove_promo_image, :remove_terms_and_conditions,
:bulk_update, :resend_confirmation], Enterprise do |enterprise|
OpenFoodNetwork::Permissions.new(user).editable_enterprises.include? enterprise
end
can [:welcome, :register], Enterprise do |enterprise|

162
app/models/spree/address.rb Normal file
View File

@@ -0,0 +1,162 @@
# frozen_string_literal: true
module Spree
class Address < ActiveRecord::Base
include AddressDisplay
belongs_to :country, class_name: "Spree::Country"
belongs_to :state, class_name: "Spree::State"
has_one :enterprise, dependent: :restrict_with_exception
has_many :shipments
validates :firstname, :lastname, :address1, :city, :country, presence: true
validates :zipcode, presence: true, if: :require_zipcode?
validates :phone, presence: true, if: :require_phone?
validate :state_validate
after_save :touch_enterprise
alias_attribute :first_name, :firstname
alias_attribute :last_name, :lastname
delegate :name, to: :state, prefix: true, allow_nil: true
geocoded_by :geocode_address
def self.default
country = begin
Spree::Country.find(Spree::Config[:default_country_id])
rescue StandardError
Spree::Country.first
end
new(country: country)
end
def full_name
"#{firstname} #{lastname}".strip
end
def state_text
state.try(:abbr) || state.try(:name) || state_name
end
def same_as?(other)
return false if other.nil?
attributes.except('id', 'updated_at', 'created_at') ==
other.attributes.except('id', 'updated_at', 'created_at')
end
alias same_as same_as?
def to_s
"#{full_name}: #{address1}"
end
def clone
self.class.new(attributes.except('id', 'updated_at', 'created_at'))
end
def ==(other)
self_attrs = attributes
other_attrs = other.respond_to?(:attributes) ? other.attributes : {}
[self_attrs, other_attrs].each { |attrs|
attrs.except!('id', 'created_at', 'updated_at', 'order_id')
}
self_attrs == other_attrs
end
def empty?
attributes.except('id', 'created_at', 'updated_at', 'order_id', 'country_id').all? { |_, v|
v.nil?
}
end
# Generates an ActiveMerchant compatible address hash
def active_merchant_hash
{
name: full_name,
address1: address1,
address2: address2,
city: city,
state: state_text,
zip: zipcode,
country: country.try(:iso),
phone: phone
}
end
def geocode_address
render_address([address1, address2, zipcode, city, country.andand.name, state.andand.name])
end
def full_address
render_address([address1, address2, city, zipcode, state.andand.name])
end
def address_part1
render_address([address1, address2])
end
def address_part2
render_address([city, zipcode, state.andand.name])
end
private
def require_phone?
true
end
def require_zipcode?
true
end
def state_validate
# Skip state validation without country (also required)
# or when disabled by preference
return if country.blank? || !Spree::Config[:address_requires_state]
return unless country.states_required
# Ensure associated state belongs to country
if state.present?
if state.country == country
self.state_name = nil # not required as we have a valid state and country combo
elsif state_name.present?
self.state = nil
else
errors.add(:state, :invalid)
end
end
# Ensure state_name belongs to country without states,
# or that it matches a predefined state name/abbr
if state_name.present?
if country.states.present?
states = country.states.find_all_by_name_or_abbr(state_name)
if states.size == 1
self.state = states.first
self.state_name = nil
else
errors.add(:state, :invalid)
end
end
end
# ensure at least one state field is populated
errors.add :state, :blank if state.blank? && state_name.blank?
end
def touch_enterprise
enterprise.andand.touch
end
def render_address(parts)
parts.select(&:present?).join(', ')
end
end
end

View File

@@ -1,38 +0,0 @@
Spree::Address.class_eval do
include AddressDisplay
has_one :enterprise, dependent: :restrict_with_exception
belongs_to :country, class_name: "Spree::Country"
after_save :touch_enterprise
geocoded_by :geocode_address
delegate :name, to: :state, prefix: true, allow_nil: true
def geocode_address
render_address([address1, address2, zipcode, city, country.andand.name, state.andand.name])
end
def full_address
render_address([address1, address2, city, zipcode, state.andand.name])
end
def address_part1
render_address([address1, address2])
end
def address_part2
render_address([city, zipcode, state.andand.name])
end
private
def touch_enterprise
enterprise.andand.touch
end
def render_address(parts)
parts.select(&:present?).join(', ')
end
end

View File

@@ -0,0 +1,21 @@
# frozen_string_literal: true
module Spree
class Classification < ActiveRecord::Base
self.table_name = 'spree_products_taxons'
belongs_to :product, class_name: "Spree::Product", touch: true
belongs_to :taxon, class_name: "Spree::Taxon", touch: true
before_destroy :dont_destroy_if_primary_taxon
private
def dont_destroy_if_primary_taxon
return unless product.primary_taxon == taxon
errors.add :base, I18n.t(:spree_classification_primary_taxon_error, taxon: taxon.name,
product: product.name)
false
end
end
end

View File

@@ -1,15 +0,0 @@
Spree::Classification.class_eval do
belongs_to :product, class_name: "Spree::Product", touch: true
belongs_to :taxon, class_name: "Spree::Taxon", touch: true
before_destroy :dont_destroy_if_primary_taxon
private
def dont_destroy_if_primary_taxon
if product.primary_taxon == taxon
errors.add :base, I18n.t(:spree_classification_primary_taxon_error, taxon: taxon.name, product: product.name)
false
end
end
end

View File

@@ -1,16 +0,0 @@
require 'active_support/concern'
# This concern is used to duplicate the associations distributors and distributor_ids
# across payment method and gateway
# this fixes the inheritance problem https://github.com/openfoodfoundation/openfoodnetwork/issues/2781
module Spree
module PaymentMethodDistributors
extend ActiveSupport::Concern
def self.included(base)
base.class_eval do
has_and_belongs_to_many :distributors, join_table: 'distributors_payment_methods', class_name: 'Enterprise', foreign_key: 'payment_method_id', association_foreign_key: 'distributor_id'
end
end
end
end

View File

@@ -1,10 +1,8 @@
# frozen_string_literal: true
require 'spree/concerns/payment_method_distributors'
module Spree
class Gateway < PaymentMethod
include Spree::PaymentMethodDistributors
include PaymentMethodDistributors
delegate_belongs_to :provider, :authorize, :purchase, :capture, :void, :credit

View File

@@ -1,8 +1,8 @@
require 'open_food_network/scope_variant_to_hub'
require 'open_food_network/variant_and_line_item_naming'
require 'variant_units/variant_and_line_item_naming'
Spree::LineItem.class_eval do
include OpenFoodNetwork::VariantAndLineItemNaming
include VariantUnits::VariantAndLineItemNaming
include LineItemBasedAdjustmentHandling
has_and_belongs_to_many :option_values, join_table: 'spree_option_values_line_items', class_name: 'Spree::OptionValue'

View File

@@ -0,0 +1,18 @@
# frozen_string_literal: true
module Spree
class LogEntry < ActiveRecord::Base
belongs_to :source, polymorphic: true
# Fix for Spree #1767
# If a payment fails, we want to make sure we keep the record of it failing
after_rollback :save_anyway
def save_anyway
log = Spree::LogEntry.new
log.source = source
log.details = details
log.save!
end
end
end

View File

@@ -194,8 +194,6 @@ Spree::Order.class_eval do
end
# After changing line items of a completed order
# TODO: perhaps this should be triggered from a controller
# rather than an after_save callback?
def update_shipping_fees!
shipments.each do |shipment|
next if shipment.shipped?
@@ -222,8 +220,6 @@ Spree::Order.class_eval do
end
# After changing line items of a completed order
# TODO: perhaps this should be triggered from a controller
# rather than an after_save callback?
def update_payment_fees!
payments.each do |payment|
next if payment.completed?

View File

@@ -1,11 +1,9 @@
# frozen_string_literal: true
require 'spree/concerns/payment_method_distributors'
module Spree
class PaymentMethod < ActiveRecord::Base
include Spree::Core::CalculatedAdjustments
include Spree::PaymentMethodDistributors
include PaymentMethodDistributors
acts_as_taggable
acts_as_paranoid

8
app/models/spree/role.rb Normal file
View File

@@ -0,0 +1,8 @@
# frozen_string_literal: true
module Spree
class Role < ActiveRecord::Base
has_and_belongs_to_many :users, join_table: 'spree_roles_users',
class_name: Spree.user_class.to_s
end
end

View File

@@ -90,7 +90,7 @@ module Spree
end
def selected_shipping_rate
shipping_rates.where(selected: true).first
shipping_rates.find_by(selected: true)
end
def selected_shipping_rate_id
@@ -294,7 +294,7 @@ module Spree
record = true
while record
random = "H#{Array.new(11) { rand(9) }.join}"
record = self.class.where(number: random).first
record = self.class.find_by(number: random)
end
self.number = random
end

View File

@@ -0,0 +1,10 @@
# frozen_string_literal: true
module Spree
class ShippingCategory < ActiveRecord::Base
validates :name, presence: true
has_many :products
has_many :shipping_method_categories
has_many :shipping_methods, through: :shipping_method_categories
end
end

View File

@@ -0,0 +1,132 @@
# frozen_string_literal: true
module Spree
class ShippingMethod < ActiveRecord::Base
include Spree::Core::CalculatedAdjustments
DISPLAY = [:both, :front_end, :back_end].freeze
acts_as_taggable
default_scope -> { where(deleted_at: nil) }
has_many :shipments
has_many :shipping_method_categories
has_many :shipping_categories, through: :shipping_method_categories
has_many :shipping_rates
has_many :distributor_shipping_methods
has_many :distributors, through: :distributor_shipping_methods,
class_name: 'Enterprise',
foreign_key: 'distributor_id'
has_and_belongs_to_many :zones, join_table: 'spree_shipping_methods_zones',
class_name: 'Spree::Zone',
foreign_key: 'shipping_method_id'
validates :name, presence: true
validate :distributor_validation
validate :at_least_one_shipping_category
after_save :touch_distributors
scope :managed_by, lambda { |user|
if user.has_spree_role?('admin')
where(nil)
else
joins(:distributors).
where('distributors_shipping_methods.distributor_id IN (?)',
user.enterprises.select(&:id)).
select('DISTINCT spree_shipping_methods.*')
end
}
scope :for_distributors, ->(distributors) {
non_unique_matches = unscoped.joins(:distributors).where(enterprises: { id: distributors })
where(id: non_unique_matches.map(&:id))
}
scope :for_distributor, lambda { |distributor|
joins(:distributors).
where('enterprises.id = ?', distributor)
}
scope :by_name, -> { order('spree_shipping_methods.name ASC') }
scope :display_on_checkout, -> {
where("spree_shipping_methods.display_on is null OR spree_shipping_methods.display_on = ''")
}
def adjustment_label
I18n.t('shipping')
end
# Here we allow checkout with shipping methods without zones (see issue #3928 for details)
# and also checkout with addresses outside of the zones of the selected shipping method
# This method could be used, like in Spree, to validate shipping method zones on checkout.
def include?(address)
address.present?
end
def build_tracking_url(tracking)
tracking_url.gsub(/:tracking/, tracking) unless tracking.blank? || tracking_url.blank?
end
def self.calculators
spree_calculators.__send__ model_name_without_spree_namespace
end
# Some shipping methods are only meant to be set via backend
def frontend?
display_on != "back_end"
end
def has_distributor?(distributor)
distributors.include?(distributor)
end
# Checks whether the shipping method is of delivery type, meaning that it
# requires the user to specify a ship address at checkout.
#
# @return [Boolean]
def delivery?
require_ship_address
end
# Return the services (pickup, delivery) that different distributors provide, in the format:
# {distributor_id => {pickup: true, delivery: false}, ...}
def self.services
Hash[
Spree::ShippingMethod.
joins(:distributor_shipping_methods).
group('distributor_id').
select("distributor_id").
select("BOOL_OR(spree_shipping_methods.require_ship_address = 'f') AS pickup").
select("BOOL_OR(spree_shipping_methods.require_ship_address = 't') AS delivery").
map { |sm| [sm.distributor_id.to_i, { pickup: sm.pickup, delivery: sm.delivery }] }
]
end
def self.on_backend_query
"#{table_name}.display_on != 'front_end' OR #{table_name}.display_on IS NULL"
end
def self.on_frontend_query
"#{table_name}.display_on != 'back_end' OR #{table_name}.display_on IS NULL"
end
private
def at_least_one_shipping_category
return unless shipping_categories.empty?
errors[:base] << "You need to select at least one shipping category"
end
def touch_distributors
distributors.each do |distributor|
distributor.touch if distributor.persisted?
end
end
def distributor_validation
validates_with DistributorsValidator
end
end
end

View File

@@ -0,0 +1,8 @@
# frozen_string_literal: true
module Spree
class ShippingMethodCategory < ActiveRecord::Base
belongs_to :shipping_method, class_name: 'Spree::ShippingMethod'
belongs_to :shipping_category, class_name: 'Spree::ShippingCategory'
end
end

View File

@@ -1,90 +0,0 @@
Spree::ShippingMethod.class_eval do
acts_as_taggable
has_many :distributor_shipping_methods
has_many :distributors, through: :distributor_shipping_methods, class_name: 'Enterprise', foreign_key: 'distributor_id'
after_save :touch_distributors
validate :distributor_validation
scope :managed_by, lambda { |user|
if user.has_spree_role?('admin')
where(nil)
else
joins(:distributors).
where('distributors_shipping_methods.distributor_id IN (?)', user.enterprises.select(&:id)).
select('DISTINCT spree_shipping_methods.*')
end
}
scope :for_distributors, ->(distributors) {
non_unique_matches = unscoped.joins(:distributors).where(enterprises: { id: distributors })
where(id: non_unique_matches.map(&:id))
}
scope :for_distributor, lambda { |distributor|
joins(:distributors).
where('enterprises.id = ?', distributor)
}
scope :by_name, -> { order('spree_shipping_methods.name ASC') }
scope :display_on_checkout, -> { where("spree_shipping_methods.display_on is null OR spree_shipping_methods.display_on = ''") }
# Return the services (pickup, delivery) that different distributors provide, in the format:
# {distributor_id => {pickup: true, delivery: false}, ...}
def self.services
Hash[
Spree::ShippingMethod.
joins(:distributor_shipping_methods).
group('distributor_id').
select("distributor_id").
select("BOOL_OR(spree_shipping_methods.require_ship_address = 'f') AS pickup").
select("BOOL_OR(spree_shipping_methods.require_ship_address = 't') AS delivery").
map { |sm| [sm.distributor_id.to_i, { pickup: sm.pickup, delivery: sm.delivery }] }
]
end
# This method is overriden so that we can remove the restriction added in Spree
# Spree restricts shipping method calculators to the ones that inherit from Spree::Shipping::ShippingCalculator
# Spree::Shipping::ShippingCalculator makes sure that calculators are able to handle packages and not orders as input
# This is not necessary in OFN because calculators in OFN are already customized to work with different types of input
def self.calculators
spree_calculators.send model_name_without_spree_namespace
end
# This is bypassing the validation of shipping method zones on checkout
# It allows checkout using shipping methods without zones (see issue #3928 for details)
# and it allows checkout with addresses outside of the zones of the selected shipping method
def include?(address)
address.present?
end
def has_distributor?(distributor)
distributors.include?(distributor)
end
def adjustment_label
I18n.t('shipping')
end
# Checks whether the shipping method is of delivery type, meaning that it
# requires the user to specify a ship address at checkout. Note this is
# a setting we added onto the +spree_shipping_methods+ table.
#
# @return [Boolean]
def delivery?
require_ship_address
end
private
def touch_distributors
distributors.each do |distributor|
distributor.touch if distributor.persisted?
end
end
def distributor_validation
validates_with DistributorsValidator
end
end

View File

@@ -0,0 +1,38 @@
# frozen_string_literal: true
module Spree
class ShippingRate < ActiveRecord::Base
belongs_to :shipment, class_name: 'Spree::Shipment'
belongs_to :shipping_method, class_name: 'Spree::ShippingMethod'
scope :frontend,
-> {
includes(:shipping_method).
where(ShippingMethod.on_frontend_query).
references(:shipping_method).
order("cost ASC")
}
scope :backend,
-> {
includes(:shipping_method).
where(ShippingMethod.on_backend_query).
references(:shipping_method).
order("cost ASC")
}
delegate :order, :currency, to: :shipment
delegate :name, to: :shipping_method
def display_price
price = if Spree::Config[:shipment_inc_vat]
(1 + Spree::TaxRate.default) * cost
else
cost
end
Spree::Money.new(price, { currency: currency })
end
alias_method :display_cost, :display_price
end
end

113
app/models/spree/taxon.rb Normal file
View File

@@ -0,0 +1,113 @@
# frozen_string_literal: true
module Spree
class Taxon < ActiveRecord::Base
acts_as_nested_set dependent: :destroy
belongs_to :taxonomy, class_name: 'Spree::Taxonomy', touch: true
has_many :classifications, dependent: :destroy
has_many :products, through: :classifications
before_create :set_permalink
validates :name, presence: true
has_attached_file :icon,
styles: { mini: '32x32>', normal: '128x128>' },
default_style: :mini,
url: '/spree/taxons/:id/:style/:basename.:extension',
path: ':rails_root/public/spree/taxons/:id/:style/:basename.:extension',
default_url: '/assets/default_taxon.png'
include Spree::Core::S3Support
supports_s3 :icon
# Indicate which filters should be used for this taxon
def applicable_filters
[]
end
# Return meta_title if set otherwise generates from root name and/or taxon name
def seo_title
if meta_title
meta_title
else
root? ? name : "#{root.name} - #{name}"
end
end
# Creates permalink based on Stringex's .to_url method
def set_permalink
if parent.present?
self.permalink = [parent.permalink, permalink_end].join('/')
elsif permalink.blank?
self.permalink = name.to_url
end
end
# For #2759
def to_param
permalink
end
def active_products
scope = products.active
scope
end
def pretty_name
ancestor_chain = ancestors.inject("") do |name, ancestor|
name += "#{ancestor.name} -> "
end
ancestor_chain + name.to_s
end
# Find all the taxons of supplied products for each enterprise, indexed by enterprise.
# Format: {enterprise_id => [taxon_id, ...]}
def self.supplied_taxons
taxons = {}
Spree::Taxon.
joins(products: :supplier).
select('spree_taxons.*, enterprises.id AS enterprise_id').
each do |t|
taxons[t.enterprise_id.to_i] ||= Set.new
taxons[t.enterprise_id.to_i] << t.id
end
taxons
end
# Find all the taxons of distributed products for each enterprise, indexed by enterprise.
# May return :all taxons (distributed in open and closed order cycles),
# or :current taxons (distributed in an open order cycle).
#
# Format: {enterprise_id => [taxon_id, ...]}
def self.distributed_taxons(which_taxons = :all)
ents_and_vars = ExchangeVariant.joins(exchange: :order_cycle).merge(Exchange.outgoing)
.select("DISTINCT variant_id, receiver_id AS enterprise_id")
ents_and_vars = ents_and_vars.merge(OrderCycle.active) if which_taxons == :current
taxons = Spree::Taxon
.select("DISTINCT spree_taxons.id, ents_and_vars.enterprise_id")
.joins(products: :variants_including_master)
.joins("
INNER JOIN (#{ents_and_vars.to_sql}) AS ents_and_vars
ON spree_variants.id = ents_and_vars.variant_id")
taxons.each_with_object({}) do |t, ts|
ts[t.enterprise_id.to_i] ||= Set.new
ts[t.enterprise_id.to_i] << t.id
end
end
private
def permalink_end
return name.to_url if permalink.blank?
permalink.split('/').last
end
end
end

View File

@@ -1,47 +0,0 @@
Spree::Taxon.class_eval do
has_many :classifications, dependent: :destroy
# Indicate which filters should be used for this taxon
def applicable_filters
fs = []
# fs << Spree::ProductFilters.distributor_filter if Spree::ProductFilters.respond_to? :distributor_filter
fs
end
# Find all the taxons of supplied products for each enterprise, indexed by enterprise.
# Format: {enterprise_id => [taxon_id, ...]}
def self.supplied_taxons
taxons = {}
Spree::Taxon.
joins(products: :supplier).
select('spree_taxons.*, enterprises.id AS enterprise_id').
each do |t|
taxons[t.enterprise_id.to_i] ||= Set.new
taxons[t.enterprise_id.to_i] << t.id
end
taxons
end
# Find all the taxons of distributed products for each enterprise, indexed by enterprise.
# May return :all taxons (distributed in open and closed order cycles),
# or :current taxons (distributed in an open order cycle).
#
# Format: {enterprise_id => [taxon_id, ...]}
def self.distributed_taxons(which_taxons = :all)
ents_and_vars = ExchangeVariant.joins(exchange: :order_cycle).merge(Exchange.outgoing)
.select("DISTINCT variant_id, receiver_id AS enterprise_id")
ents_and_vars = ents_and_vars.merge(OrderCycle.active) if which_taxons == :current
taxons = Spree::Taxon
.select("DISTINCT spree_taxons.id, ents_and_vars.enterprise_id").joins(products: :variants_including_master)
.joins("INNER JOIN (#{ents_and_vars.to_sql}) AS ents_and_vars ON spree_variants.id = ents_and_vars.variant_id")
taxons.each_with_object({}) do |t, ts|
ts[t.enterprise_id.to_i] ||= Set.new
ts[t.enterprise_id.to_i] << t.id
end
end
end

View File

@@ -0,0 +1,24 @@
# frozen_string_literal: true
module Spree
class Taxonomy < ActiveRecord::Base
validates :name, presence: true
has_many :taxons
has_one :root, -> { where parent_id: nil }, class_name: "Spree::Taxon", dependent: :destroy
after_save :set_name
default_scope -> { order("#{table_name}.position") }
private
def set_name
if root
root.update_column(:name, name)
else
self.root = Taxon.create!(taxonomy_id: id, name: name)
end
end
end
end

View File

@@ -7,6 +7,13 @@ module Spree
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'
has_and_belongs_to_many :spree_roles,
join_table: 'spree_roles_users',
foreign_key: "user_id",
class_name: "Spree::Role"
has_many :spree_orders, foreign_key: "user_id", class_name: "Spree::Order"
before_validation :set_login
before_destroy :check_completed_orders
@@ -41,6 +48,12 @@ module Spree
User.admin.count > 0
end
# Whether a user has a role or not.
def has_spree_role?(role_in_question)
spree_roles.where(name: role_in_question.to_s).any?
end
# Checks whether the specified user is a superadmin, with full control of the instance
def admin?
has_spree_role?('admin')
end
@@ -107,14 +120,6 @@ module Spree
end
end
# Checks whether the specified user is a superadmin, with full control of the
# instance
#
# @return [Boolean]
def superadmin?
has_spree_role?('admin')
end
def generate_spree_api_key!
self.spree_api_key = SecureRandom.hex(24)
save!
@@ -125,6 +130,10 @@ module Spree
save!
end
def last_incomplete_spree_order
spree_orders.incomplete.where(created_by_id: id).order('created_at DESC').first
end
protected
def password_required?

View File

@@ -1,5 +1,5 @@
require 'open_food_network/enterprise_fee_calculator'
require 'open_food_network/variant_and_line_item_naming'
require 'variant_units/variant_and_line_item_naming'
require 'concerns/variant_stock'
Spree::Variant.class_eval do
@@ -8,7 +8,7 @@ Spree::Variant.class_eval do
# This file may be double-loaded in delayed job environment, so we check before
# removing the Spree method to prevent error.
remove_method :options_text if instance_methods(false).include? :options_text
include OpenFoodNetwork::VariantAndLineItemNaming
include VariantUnits::VariantAndLineItemNaming
include VariantStock
has_many :exchange_variants

View File

@@ -6,7 +6,7 @@ class Api::Admin::EnterpriseSerializer < ActiveModel::Serializer
:preferred_product_selection_from_inventory_only,
:preferred_show_customer_names_to_suppliers, :owner, :contact, :users, :tag_groups,
:default_tag_group, :require_login, :allow_guest_orders, :allow_order_changes,
:logo, :promo_image
:logo, :promo_image, :terms_and_conditions, :terms_and_conditions_file_name
has_one :owner, serializer: Api::Admin::UserSerializer
has_many :users, serializer: Api::Admin::UserSerializer
@@ -20,6 +20,12 @@ class Api::Admin::EnterpriseSerializer < ActiveModel::Serializer
attachment_urls(object.promo_image, [:thumb, :medium, :large])
end
def terms_and_conditions
return unless @object.terms_and_conditions.file?
@object.terms_and_conditions.url
end
def tag_groups
object.tag_rules.prioritised.reject(&:is_default).each_with_object([]) do |tag_rule, tag_groups|
tag_group = find_match(tag_groups, tag_rule.preferred_customer_tags.

View File

@@ -1,3 +1,3 @@
class Api::StateSerializer < ActiveModel::Serializer
attributes :id, :name, :abbr
attributes :id, :name, :abbr, :country_id
end

View File

@@ -32,7 +32,7 @@ class OrderTaxAdjustmentsFetcher
end
def line_item_adjustments
table[:adjustable_id].eq(order.line_item_ids.join(','))
table[:adjustable_id].eq_any(order.line_item_ids)
.and(table[:adjustable_type].eq('Spree::LineItem'))
end

View File

@@ -25,7 +25,7 @@ module PermittedAttributes
[
:id, :name, :visible, :permalink, :owner_id, :contact_name, :email_address, :phone,
:is_primary_producer, :sells, :website, :facebook, :instagram, :linkedin, :twitter,
:description, :long_description, :logo, :promo_image,
:description, :long_description, :logo, :promo_image, :terms_and_conditions,
:allow_guest_orders, :allow_order_changes, :require_login, :enable_subscriptions,
:abn, :acn, :charges_sales_tax, :display_invoice_logo, :invoice_text,
:preferred_product_selection_from_inventory_only, :preferred_shopfront_message,

View File

@@ -0,0 +1,11 @@
# frozen_string_literal: true
class ProductFilters
PRODUCT_FILTERS = [
'query', 'producerFilter', 'categoryFilter', 'sorting', 'importDateFilter'
].freeze
def extract(params)
params.select { |key, _value| PRODUCT_FILTERS.include?(key) }
end
end

View File

@@ -2,7 +2,7 @@
require "open_food_network/i18n_inflections"
module OpenFoodNetwork
module VariantUnits
class OptionValueNamer
def initialize(variant = nil)
@variant = variant
@@ -39,7 +39,6 @@ module OpenFoodNetwork
if @variant.unit_value.present?
if %w(weight volume).include? @variant.product.variant_unit
value, unit_name = option_value_value_unit_scaled
else
value = @variant.unit_value
unit_name = pluralize(@variant.product.variant_unit_name, value)
@@ -63,21 +62,44 @@ module OpenFoodNetwork
end
def scale_for_unit_value
units = { 'weight' => { 1.0 => 'g', 1000.0 => 'kg', 1_000_000.0 => 'T' },
'volume' => { 0.001 => 'mL', 1.0 => 'L', 1000.0 => 'kL' } }
units = {
'weight' => {
1.0 => { 'name' => 'g', 'system' => 'metric' },
28.35 => { 'name' => 'oz', 'system' => 'imperial' },
453.6 => { 'name' => 'lb', 'system' => 'imperial' },
1000.0 => { 'name' => 'kg', 'system' => 'metric' },
1_000_000.0 => { 'name' => 'T', 'system' => 'metric' }
},
'volume' => {
0.001 => { 'name' => 'mL', 'system' => 'metric' },
1.0 => { 'name' => 'L', 'system' => 'metric' },
1000.0 => { 'name' => 'kL', 'system' => 'metric' }
}
}
# Find the largest available unit where unit_value comes to >= 1 when expressed in it.
# If there is none available where this is true, use the smallest available unit.
unit = units[@variant.product.variant_unit].select { |scale, _unit_name|
@variant.unit_value / scale >= 1
}.to_a.last
unit = units[@variant.product.variant_unit].first if unit.nil?
scales = units[@variant.product.variant_unit]
product_scale = @variant.product.variant_unit_scale
product_scale_system = scales[product_scale.to_f]['system']
unit
largest_unit = find_largest_unit(scales, product_scale_system)
[largest_unit[0], largest_unit[1]["name"]]
end
# Find the largest available and compatible unit where unit_value comes
# to >= 1 when expressed in it.
# If there is none available where this is true, use the smallest available unit.
def find_largest_unit(scales, product_scale_system)
largest_unit = scales.select { |scale, unit_info|
unit_info['system'] == product_scale_system &&
@variant.unit_value / scale >= 1
}.max
return scales.first if largest_unit.nil?
largest_unit
end
def pluralize(unit_name, count)
I18nInflections.pluralize(unit_name, count)
OpenFoodNetwork::I18nInflections.pluralize(unit_name, count)
end
end
end

View File

@@ -2,9 +2,9 @@
# It contains all of our logic for creating and naming option values (which are associated
# with both models) and methods for printing human readable "names" for instances of these models.
require 'open_food_network/option_value_namer'
require 'variant_units/option_value_namer'
module OpenFoodNetwork
module VariantUnits
module VariantAndLineItemNaming
# Copied and modified from Spree::Variant
def options_text
@@ -18,7 +18,24 @@ module OpenFoodNetwork
order("#{Spree::OptionType.table_name}.position asc")
end
values.map(&:presentation).to_sentence(words_connector: ", ", two_words_connector: ", ")
values.map { |option_value|
presentation(option_value)
}.to_sentence(words_connector: ", ", two_words_connector: ", ")
end
def presentation(option_value)
return option_value.presentation unless option_value.option_type.name == "unit_weight"
return display_as if has_attribute?(:display_as) && display_as.present?
return variant.display_as if variant_display_as?
option_value.presentation
end
def variant_display_as?
respond_to?(:variant) && variant.present? &&
variant.respond_to?(:display_as) && variant.display_as.present?
end
def product_and_full_name
@@ -48,9 +65,11 @@ module OpenFoodNetwork
end
def unit_to_display
return options_text if !has_attribute?(:display_as) || display_as.blank?
return display_as if has_attribute?(:display_as) && display_as.present?
display_as
return variant.display_as if variant_display_as?
options_text
end
def update_units
@@ -84,7 +103,7 @@ module OpenFoodNetwork
if has_attribute?(:display_as) && display_as.present?
display_as
else
option_value_namer = OpenFoodNetwork::OptionValueNamer.new self
option_value_namer = VariantUnits::OptionValueNamer.new self
option_value_namer.name
end
end

View File

@@ -31,3 +31,16 @@
= f.label :invoice_text, t('.invoice_text')
.omega.eight.columns
= f.text_area :invoice_text, style: "width: 100%; height: 100px;"
.row
.alpha.three.columns
= f.label :terms_and_conditions, t('.terms_and_conditions')
.omega.eight.columns
%a{ href: '{{ Enterprise.terms_and_conditions }}', ng: { if: 'Enterprise.terms_and_conditions' } }
= '{{ Enterprise.terms_and_conditions_file_name }}'
.pad-top
= f.file_field :terms_and_conditions
.pad-top
%a.button.red{ href: '', ng: {click: 'removeTermsAndConditions()', if: 'Enterprise.terms_and_conditions'} }
= t('.remove_terms_and_conditions')

View File

@@ -7,7 +7,7 @@
%img{ class: 'image-field-group__preview-image', ng: { src: '{{ Enterprise.logo.medium }}', if: 'Enterprise.logo' } }
= f.file_field :logo
%a.button.red{ href: '', ng: {click: 'removeLogo()', if: 'Enterprise.logo'} }
= t('admin.enterprises.remove_logo.remove')
= t('.remove_logo')
.row.page-admin-enterprises-form__promo-image-field-group.image-field-group
.alpha.three.columns
@@ -23,4 +23,4 @@
%img{ class: 'image-field-group__preview-image', ng: { src: '{{ Enterprise.promo_image.large }}', if: 'Enterprise.promo_image' } }
= f.file_field :promo_image
%a.button.red{ href: '', ng: {click: 'removePromoImage()', if: 'Enterprise.promo_image'} }
= t('admin.enterprises.remove_promo_image.remove')
= t('.remove_promo_image')

View File

@@ -1,5 +1,5 @@
%h1
=t'new_order_cycle'
- content_for :page_title do
=t('new_order_cycle')
- ng_controller = order_cycles_simple_form ? 'AdminSimpleCreateOrderCycleCtrl' : 'AdminCreateOrderCycleCtrl'
= admin_inject_order_cycle_instance

View File

@@ -14,6 +14,7 @@
= render "checkout/shipping", f: f
= render "checkout/payment", f: f
= render "checkout/already_ordered", f: f if show_bought_items?
= render "checkout/terms_and_conditions", f: f
%p
%button.button.primary{type: :submit}
= t :checkout_send

View File

@@ -13,8 +13,6 @@
"ng-class" => "{valid: payment.$valid, open: accordion.payment}"}
= render 'checkout/accordion_heading'
-# TODO render this in Angular instead of server-side
-# The problem being how to render the partials
.row
.small-12.medium-12.large-6.columns
- available_payment_methods.each do |method|

View File

@@ -0,0 +1,2 @@
%p.small
= t('.message_html', terms_and_conditions_link: link_to( t( '.link_text' ), current_order.distributor.terms_and_conditions.url, target: '_blank')) if current_order.distributor.terms_and_conditions.file?

View File

@@ -2,7 +2,6 @@
.row
.small-12.text-center.columns
%h1
/ TODO: Rohan - logo asset & width is content manageable:
%img{src: image_path("logo-white-notext.png"), title: Spree::Config.site_name}
%br/
%a.button.transparent{href: "/shops"}

View File

@@ -1,29 +1,34 @@
:javascript
$(document).ready(function() {
var in_iframe = function(){
try {
return window.self !== window.top;
} catch (e) {
return true;
var isInIframe = function(){
try {
return window.self !== window.top;
} catch (e) {
return true;
}
};
document.addEventListener(
'DOMContentLoaded',
function() {
var inIframe = isInIframe();
var embedded_styles_active = $('body.off-canvas').hasClass('embedded');
var set_shopfront_styles = function (state) {
$.ajax({
url: '/embedded_shopfront/' + state,
type: 'POST'
});
};
if (inIframe && !embedded_styles_active){
$('body.off-canvas').addClass('embedded');
set_shopfront_styles('enable');
}
};
var embedded_styles_active = $('body.off-canvas').hasClass('embedded');
var set_shopfront_styles = function(state) {
$.ajax({
url: '/embedded_shopfront/'+state,
type: 'POST'
});
};
if (in_iframe() && !embedded_styles_active){
$('body.off-canvas').addClass('embedded');
set_shopfront_styles('enable');
}
if (!in_iframe() && embedded_styles_active) {
$('body.off-canvas').removeClass('embedded');
set_shopfront_styles('disable');
}
});
if (!inIframe && embedded_styles_active) {
$('body.off-canvas').removeClass('embedded');
set_shopfront_styles('disable');
}
},
false
);

View File

@@ -18,14 +18,14 @@
= stylesheet_link_tag "darkswarm/all"
= csrf_meta_tags
%body{class: body_classes, "body-scroll" => true , ng: {app: "Darkswarm"}}
%body{ class: body_classes, "body-scroll" => true , ng: { app: 'Darkswarm' }}
/ [if lte IE 8]
= render partial: "shared/ie_warning"
= javascript_include_tag "iehack"
= render "layouts/shopfront_script" if @shopfront_layout
.off-canvas-wrap{offcanvas: true}
.off-canvas-wrap{ offcanvas: true }
.fixed.off-canvas-fixed
= render "shared/menu/menu" unless @hide_menu
= yield :page_alert
@@ -40,7 +40,8 @@
= render "layouts/bugsnag_js"
- if Spree::Config.stripe_connect_enabled
%script{:src => "https://js.stripe.com/v3/", :type => "text/javascript"}
= render "shared/stripe_js"
- if !ContentConfig.open_street_map_enabled
%script{src: "//maps.googleapis.com/maps/api/js?libraries=places,geometry#{ ENV['GOOGLE_MAPS_API_KEY'] ? '&key=' + ENV['GOOGLE_MAPS_API_KEY'] : ''} "}

View File

@@ -0,0 +1,5 @@
- if Rails.env.test?
%script{type: "text/javascript"}
= render file: "spec/support/fixtures/stripejs-mock.js"
- else
%script{src: "https://js.stripe.com/v3/", type: "text/javascript"}

View File

@@ -3,9 +3,9 @@
= render partial: 'spree/shared/error_messages', locals: { target: @image }
- content_for :page_actions do
%li= button_link_to t('spree.back_to_images_list'), admin_product_images_url(@product), icon: 'icon-arrow-left'
%li= button_link_to t('spree.back_to_images_list'), admin_product_images_url(@product, @url_filters), icon: 'icon-arrow-left'
= form_for [:admin, @product, @image], html: { multipart: true } do |f|
= form_for [:admin, @product, @image], url: admin_product_image_path(@product, @image, @url_filters), html: { multipart: true } do |f|
%fieldset
%legend{align: "center"}= @image.attachment_file_name
.field.alpha.three.columns.align-center
@@ -18,4 +18,4 @@
.form-buttons.filter-actions.actions
= button t('spree.actions.update'), 'icon-refresh'
%span.or= t('spree.or')
= link_to t('spree.actions.cancel'), admin_product_images_url(@product), id: 'cancel_link', class: 'button icon-remove'
= link_to t('spree.actions.cancel'), admin_product_images_url(@product, @url_filters), id: 'cancel_link', class: 'button icon-remove'

View File

@@ -2,7 +2,7 @@
= render partial: 'spree/admin/shared/product_tabs', locals: { current: 'Images'}
- content_for :page_actions do
%li= link_to_with_icon('icon-plus', t('spree.new_image'), new_admin_product_image_url(@product), id: 'new_image_link', class: 'button')
%li= link_to_with_icon('icon-plus', t('spree.new_image'), new_admin_product_image_url(@product, @url_filters), id: 'new_image_link', class: 'button')
#images
@@ -11,7 +11,7 @@
= t('spree.no_images_found')
\.
- else
%table.index.sortable{ "data-sortable-link" => "#{update_positions_admin_product_images_url(@product)}" }
%table.index.sortable{ "data-sortable-link" => "#{update_positions_admin_product_images_url(@product, @url_filters)}" }
%colgroup
%col{ style: "width: 5%" }/
%col{ style: "width: 10%" }/
@@ -36,5 +36,5 @@
%td= options_text_for(image)
%td= image.alt
%td.actions
= link_to_with_icon 'icon-edit', t('spree.edit'), edit_admin_product_image_url(@product, image), no_text: true, data: { action: 'edit'}
= link_to_delete image, { url: admin_product_image_url(@product, image), no_text: true }
= link_to_with_icon 'icon-edit', t('spree.edit'), edit_admin_product_image_url(@product, image, @url_filters), no_text: true, data: { action: 'edit'}
= link_to_delete image, { url: admin_product_image_url(@product, image, @url_filters), no_text: true }

View File

@@ -1,10 +1,10 @@
= form_for [:admin, @product, @image], html: { multipart: true } do |f|
= form_for [:admin, @product, @image], url: admin_product_images_path(@product, @image, @url_filters), html: { multipart: true } do |f|
%fieldset
%legend{ align: "center" }= t('spree.new_image')
= render partial: 'form', locals: { f: f }
.form-buttons.filter-actions.actions
= button t('spree.actions.update'), 'icon-refresh'
%span.or= t('spree.or')
= link_to_with_icon 'icon-remove', t('spree.actions.cancel'), admin_product_images_url(@product), id: 'cancel_link', class: 'button'
= link_to_with_icon 'icon-remove', t('spree.actions.cancel'), admin_product_images_url(@product, @url_filters), id: 'cancel_link', class: 'button'
= javascript_include_tag 'admin/spree/images/new.js'

View File

@@ -0,0 +1,45 @@
- if use_billing
.field{style: "position: absolute;margin-top: -15px;right: 0;"}
%span
= check_box_tag 'order[use_billing]', '1', (!(@order.bill_address.empty? && @order.ship_address.empty?) && @order.bill_address.same_as?(@order.ship_address))
= label_tag 'order[use_billing]', Spree.t(:use_billing_address)
- is_shipping_address = name == Spree.t(:shipping_address)
- s_or_b = is_shipping_address ? 's' : 'b'
- display_style = (use_billing && (!(@order.bill_address.empty? && @order.ship_address.empty?) && @order.bill_address == @order.ship_address)) ? 'none' : 'block'
%div{id: "#{is_shipping_address ? 'shipping' : 'billing'}", style: "display: #{display_style}"}
%div{class: "field"}
= f.label :firstname, Spree.t(:first_name) + ':'
= f.text_field :firstname, class: 'fullwidth'
%div{class: "field"}
= f.label :lastname, Spree.t(:last_name) + ':'
= f.text_field :lastname, class: 'fullwidth'
- if Spree::Config[:company]
%div{class: "field"}
= f.label :company, Spree.t(:company) + ':'
= f.text_field :company, class: 'fullwidth'
%div{class: "field"}
= f.label :address1, Spree.t(:street_address) + ':'
= f.text_field :address1, class: 'fullwidth'
%div{class: "field"}
= f.label :address2, Spree.t(:street_address_2) + ':'
= f.text_field :address2, class: 'fullwidth'
%div{class: "field"}
= f.label :city, Spree.t(:city) + ':'
= f.text_field :city, class: 'fullwidth'
%div{class: "field"}
= f.label :zipcode, Spree.t(:zip) + ':'
= f.text_field :zipcode, class: 'fullwidth'
%div{class: "field"}
= f.label :country_id, Spree.t(:country) + ':'
%span{id: "#{s_or_b}country"}
= f.collection_select :country_id, available_countries, :id, :name, {}, {class: 'select2 fullwidth', onchange: "update_state('#{s_or_b}')"}
%div{class: "field"}
= f.label :state_id, Spree.t(:state) + ':'
%span{id: "#{s_or_b}state"}
= f.collection_select :state_id, f.object.country.states.sort, :id, :name, {include_blank: true}, {class: 'select2 fullwidth', disabled: f.object.country.states.empty?}
%div{class: "field"}
= f.label :phone, Spree.t(:phone) + ':'
= f.phone_field :phone, class: 'fullwidth'

View File

@@ -11,13 +11,13 @@
%fieldset.no-border-bottom
%legend{:align => "center"}= Spree.t(:billing_address)
= f.fields_for :bill_address do |ba_form|
= render :partial => 'spree/admin/shared/address_form', :locals => { :f => ba_form, :name => Spree.t(:billing_address), :use_billing => false }
= render :partial => 'address_form', :locals => { :f => ba_form, :name => Spree.t(:billing_address), :use_billing => false }
.omega.six.columns{"data-hook" => "ship_address_wrapper"}
%fieldset.no-border-bottom
%legend{:align => "center"}= Spree.t(:shipping_address)
= f.fields_for :ship_address do |sa_form|
= render :partial => 'spree/admin/shared/address_form', :locals => { :f => sa_form, :name => Spree.t(:shipping_address), :use_billing => true }
= render :partial => 'address_form', :locals => { :f => sa_form, :name => Spree.t(:shipping_address), :use_billing => true }
.clear
@@ -26,3 +26,4 @@
- content_for :head do
= javascript_include_tag 'admin/spree/orders/address_states.js'
= javascript_include_tag 'admin/spree/orders/use_billing.js'

View File

@@ -11,7 +11,8 @@
%col{style: "width: 13%"}
%col{style: "width: 14%"}
%col{style: "width: 32%"}
%col{style: "width: 14%"}
- if spree_current_user.admin?
%col{style: "width: 14%"}
%col{style: "width: 8%"}
%col{style: "width: 8%"}
%col{style: "width: 11%"}
@@ -20,7 +21,8 @@
%th= t('.name')
%th= t('.products_distributor')
%th= t('.provider')
%th= t('.environment')
- if spree_current_user.admin?
%th= t('.environment')
%th= t('.display')
%th= t('.active')
%th.actions
@@ -33,7 +35,8 @@
= distributor.name
%br/
%td= method.class.clean_name
%td.align-center= method.environment.to_s.titleize
- if spree_current_user.admin?
%td.align-center= method.environment.to_s.titleize
%td.align-center= method.display_on.blank? ? t('.both') : t('.' + method.display_on.to_s)
%td.align-center= method.active ? t('.active_yes') : t('.active_no')
%td.actions

View File

@@ -1,6 +1,7 @@
-# = render "spree/admin/payments/source_forms/gateway", payment_method: payment_method
.stripe
%script{:src => "https://js.stripe.com/v3/", :type => "text/javascript"}
= render "shared/stripe_js"
- if Stripe.publishable_key
:javascript
angular.module('admin.payments').value("stripeObject", Stripe("#{Stripe.publishable_key}"))

View File

@@ -1,5 +1,6 @@
.stripe
%script{:src => "https://js.stripe.com/v3/", :type => "text/javascript"}
= render "shared/stripe_js"
- if Stripe.publishable_key
:javascript
angular.module('admin.payments').value("stripeObject", Stripe("#{Stripe.publishable_key}"))

View File

@@ -11,4 +11,4 @@
= f.text_field :value, class: 'autocomplete'
%td.actions
- if f.object.persisted?
= link_to_delete f.object, no_text: true
= link_to_delete f.object, { url: admin_product_product_property_url(@product, f.object, @url_filters), no_text: true }

View File

@@ -9,7 +9,7 @@
%li
= link_to_add_fields t('.add_product_properties'), 'tbody#product_properties', class: 'icon-plus button'
= form_for @product, url: admin_product_url(@product), method: :put do |f|
= form_for @product, url: admin_product_url(@product, @url_filters), method: :put do |f|
%fieldset.no-border-top
.add_product_properties
= image_tag 'select2-spinner.gif', plugin: 'spree', style: 'display:none;', id: 'busy_indicator'
@@ -46,7 +46,10 @@
%td.actions
= render partial: 'spree/admin/shared/edit_resource_links'
.form-buttons.filter-actions.actions
= button t('spree.actions.update'), 'icon-refresh'
%span.or= t('spree.or')
= link_to t('spree.actions.cancel'), admin_product_product_properties_url(@product, @url_filters), id: 'cancel_link', class: 'button icon-remove'
= hidden_field_tag 'clear_product_properties', 'true'

View File

@@ -1,5 +1,5 @@
- content_for :page_actions do
%li= button_link_to t('admin.products.back_to_products_list'), admin_products_path, :icon => 'icon-arrow-left'
%li= button_link_to t('admin.products.back_to_products_list'), "#{admin_products_path}#{(@url_filters.empty? ? "" : "#?#{@url_filters.to_query}")}", :icon => 'icon-arrow-left'
%li#new_product_link
= button_link_to t(:new_product), new_object_url, { :icon => 'icon-plus', :id => 'admin_new_product' }
@@ -8,7 +8,10 @@
= render :partial => 'spree/admin/shared/product_tabs', :locals => { :current => 'Product Details' }
= render :partial => 'spree/shared/error_messages', :locals => { :target => @product }
= form_for [:admin, @product], :method => :put, :html => { :multipart => true } do |f|
= form_for [:admin, @product], :url => admin_product_path(@product, @url_filters), :method => :put, :html => { :multipart => true } do |f|
%fieldset.no-border-top{'ng-app' => 'admin.products'}
= render :partial => 'form', :locals => { :f => f }
= render :partial => 'spree/admin/shared/edit_resource_links'
.form-buttons.filter-actions.actions
= button t(:update), 'icon-refresh'
%span.or= t(:or)
= button_link_to t(:cancel), "#{collection_url}#{(@url_filters.empty? ? "" : "#?#{@url_filters.to_query}")}", icon: 'icon-remove'

View File

@@ -1,8 +1,11 @@
= render partial: 'spree/admin/shared/product_sub_menu'
= render :partial => 'spree/admin/shared/product_tabs', :locals => { :current => 'Group Buy Options' }
= render :partial => 'spree/shared/error_messages', :locals => { :target => @product }
= render partial: 'spree/admin/shared/product_tabs', locals: { :current => 'Group Buy Options' }
= render partial: 'spree/shared/error_messages', locals: { :target => @product }
= form_for [:admin, @product], :method => :put, :html => { :multipart => true } do |f|
= form_for [:admin, @product], url: admin_product_url(@product, @url_filters), method: :put, html: { :multipart => true } do |f|
%fieldset.no-border-top
= render :partial => 'group_buy_form', :locals => { :f => f }
= render :partial => 'spree/admin/shared/edit_resource_links'
= render partial: 'group_buy_form', locals: { f: f }
.form-buttons.filter-actions.actions
= button t('spree.actions.update'), 'icon-refresh'
%span.or= t('spree.or')
= link_to t('spree.actions.cancel'), edit_admin_product_url(@product, @url_filters), id: 'cancel_link', class: 'button icon-remove'

View File

@@ -5,22 +5,20 @@
.quick_search.three.columns.alpha
%label{ for: 'quick_filter' }
%br
%input.quick-search.fullwidth{ ng: {model: 'query'}, name: "quick_filter", type: 'text', placeholder: t('admin.quick_search'), "ng-keypress" => "$event.keyCode === 13 && fetchProducts()" }
%input.quick-search.fullwidth{ ng: {model: 'q.query'}, name: "quick_filter", type: 'text', placeholder: t('admin.quick_search'), "ng-keypress" => "$event.keyCode === 13 && fetchProducts()" }
.one.columns &nbsp;
.filter_select.three.columns
%label{ for: 'producer_filter' }= t 'producer'
%br
%select.fullwidth{ id: 'producer_filter', 'ofn-select2-min-search' => 5, ng: {model: 'producerFilter', options: 'producer.id as producer.name for producer in producers'} }
%select.fullwidth{ id: 'producer_filter', 'ofn-select2-min-search' => 5, ng: {model: 'q.producerFilter', options: 'producer.id as producer.name for producer in producers'} }
.filter_select.three.columns
%label{ for: 'category_filter' }= t 'category'
%br
%select.fullwidth{ id: 'category_filter', 'ofn-select2-min-search' => 5, ng: {model: 'categoryFilter', options: 'taxon.id as taxon.name for taxon in taxons'} }
%select.fullwidth{ id: 'category_filter', 'ofn-select2-min-search' => 5, ng: {model: 'q.categoryFilter', options: 'taxon.id as taxon.name for taxon in taxons'} }
.filter_select.three.columns
%label{ for: 'import_filter' } Import Date
%br
%select.fullwidth{ id: 'import_date_filter', 'ofn-select2-min-search' => 5, ng: {model: 'importDateFilter', init: "importDates = #{@import_dates}; showLatestImport = #{@show_latest_import}"}}
%option{value: "{{date.id}}", ng: {repeat: "date in importDates" }}
{{date.name}}
%select.fullwidth{ id: 'import_date_filter', 'ofn-select2-min-search' => 5, ng: {model: 'q.importDateFilter', init: "importDates = #{@import_dates}; showLatestImport = #{@show_latest_import}", options: 'date.id as date.name for date in importDates'} }
.filter_clear.three.columns.omega
%label{ for: 'clear_all_filters' }

View File

@@ -3,12 +3,12 @@
%img.spinner{ src: image_path("spinning-circles.svg") }
%h1= t('.title')
%div.sixteen.columns.alpha{ 'ng-show' => '!RequestMonitor.loading && products.length == 0 && query.length==0' }
%div.sixteen.columns.alpha{ 'ng-show' => '!RequestMonitor.loading && products.length == 0 && q.query.length == 0' }
%h1#no_results= t('.no_products')
%div.sixteen.columns.alpha{ 'ng-show' => '!RequestMonitor.loading && products.length == 0 && query.length!=0' }
%div.sixteen.columns.alpha{ 'ng-show' => '!RequestMonitor.loading && products.length == 0 && q.query.length != 0' }
%h1#no_results
= t('.no_results')
'
{{query}}
'
{{q.query}}
'

Some files were not shown because too many files have changed in this diff Show More