Compare commits

...

673 Commits
v1.10 ... v1.12

Author SHA1 Message Date
Pau Pérez Fabregat
e23d714e83 Merge pull request #2154 from openfoodfoundation/transifex
Transifex
2018-03-19 10:29:48 +01:00
Transifex-Openfoodnetwork
ec01e55707 Updating translations for config/locales/es.yml 2018-03-19 19:56:02 +11:00
Pau Pérez Fabregat
c18b996a1b Merge pull request #2098 from Matt-Yorkley/uk/font-caching
Fix browser caching of updated icon font
2018-03-17 11:10:04 +01:00
Enrico Stano
98ea82462d Merge pull request #2136 from coopdevs/upgrade-test-dependencies
Upgrade test dependencies
2018-03-15 12:21:49 +01:00
Pau Pérez Fabregat
586a9afaae Merge pull request #2125 from KeirOsborn/order_order_cycle_list_#1884
Order order cycle list #1884
2018-03-14 19:08:28 +01:00
Pau Pérez Fabregat
f116ee156f Merge pull request #1951 from JF-Lalonde/remove_duplicate_datepicker_1947
Remove duplicated directive datepicker from index_utils directory
2018-03-14 19:08:06 +01:00
JF-Lalonde
7a9f341363 Remove duplicated directive datepicker from index_utils directory 2018-03-14 17:01:54 +11:00
Maikel Linke
ada0fa50fc Replace Rohan's email address by optional config
Rohan's email address is hard-coded, but he doesn't want to receive
these emails any more.
2018-03-14 15:30:53 +11:00
HugsDaniel
451c57da40 Changed i18n t() path to get content from locales 2018-03-14 15:01:01 +11:00
Hugo Daniel
82a752de46 Added margin bottom on table#listing_products to display a bit above the save bar 2018-03-14 13:16:31 +11:00
Matt-Yorkley
e2f3feccf0 Add comments to authentication_service.js 2018-03-14 12:13:45 +11:00
Matt-Yorkley
e6bdbccffa Ensure email links return to proper path on private shops, refactor modal logic 2018-03-14 12:13:45 +11:00
Matt-Yorkley
ea9b0eca48 Adjust wording on validation modal message 2018-03-14 12:13:45 +11:00
Matt-Yorkley
e8bc87e62b Ensure email validation link returns to /register paths properly 2018-03-14 12:13:45 +11:00
Matt-Yorkley
d7a3c50bd5 Remove underscore from resource 2018-03-14 12:13:45 +11:00
Matt-Yorkley
f5a0862655 Email confirmation modal specs 2018-03-14 12:13:45 +11:00
Matt-Yorkley
595bc5d1a5 Show confirmation message in modal 2018-03-14 12:13:45 +11:00
Matt-Yorkley
bc621a3c43 Return user to same URL from confirmation link 2018-03-14 12:13:45 +11:00
Hugs
7ebf5db1f2 Added img tag when producer.description.length==0 to display logo even when no About Us 2018-03-14 11:44:04 +11:00
Maxime Lalisse
e806f38142 Fix translation keys 2018-03-14 10:13:40 +11:00
Pau Perez
d980809a19 Upgrade shoulda-matchers from 1.1.0 to 2.8.0 2018-03-13 17:46:59 +01:00
Pau Perez
e6f6232607 Upgrade letter_opener from 1.4.1 to 1.6.0 2018-03-13 14:21:54 +01:00
Pau Perez
cce30d5762 Upgrade Knapsack from 1.5.1 to 1.16.0 2018-03-13 14:11:00 +01:00
Pau Perez
47a6ffbf66 Upgrade Capybara from 2.15.4 to 2.18.0 2018-03-13 13:58:06 +01:00
HugsDaniel
7e5eae1b8d Added testing on statusMessage display for pending changes 2018-03-13 21:03:54 +11:00
HugsDaniel
8c4d0f11d7 Changed status message with i18n t() filter to displau unsaved changes status for customers edition in admin dashboard 2018-03-13 21:03:54 +11:00
Pau Perez
d96c1fc165 Upgrade factory_girl_rails from 3.3.0 to 4.9.0
This is the last version before moving to factory_bot_rails.
2018-03-13 10:01:14 +01:00
Pau Perez
6f879cd5d9 Remove unused gem Turn
It provides runners for MiniTest and we use RSpec.
2018-03-13 09:54:26 +01:00
Pau Perez
1d75e5a671 Upgrade rspec-retry from 0.4.2 to 0.5.6 2018-03-13 09:53:20 +01:00
Pau Perez
bdd58dccf0 Upgrade Timecop from 0.8.1 to 0.9.1 2018-03-13 09:34:09 +01:00
Pau Perez
aaf5bcbb12 Upgrade rspec-rails from 3.7.1 to 3.7.2 2018-03-13 09:32:12 +01:00
Pau Pérez Fabregat
976bbd8725 Merge pull request #2124 from coopdevs/replace-mail-method-in-base-mailer-decorator
Remove deprecated reference to Spree::MailMethod
2018-03-13 08:51:11 +01:00
Enrico Stano
341604be8a Merge pull request #2094 from openfoodfoundation/transifex
Transifex
2018-03-13 08:39:11 +01:00
Enrico Stano
5ce320f8a2 Merge pull request #2133 from coopdevs/fix-sample-data
Fix shipping method creation in sample data
2018-03-12 18:39:34 +01:00
Pau Perez
6598c80f6e Fix shipping method creation in sample data 2018-03-12 16:52:56 +01:00
Keir Osborn
d4b84e55c2 order order cycle list from most lates close date to earliest on /orders page #1884 2018-03-12 11:04:50 +00:00
Pau Pérez Fabregat
6f5080923f Merge pull request #2123 from coopdevs/bring-seeds-from-ofn-install
Bring seeds from ofn install
2018-03-12 11:43:14 +01:00
Pau Pérez Fabregat
afda5cc04e Merge pull request #2115 from coopdevs/localize-sample-data
Localize sample data
2018-03-09 16:18:18 +01:00
Pau Perez
12e225e7c0 Add sample addresses in the instance's country
This ensures the address country and state are valid, meaning the state
belongs to the provided country. We use the instance's to do that.
2018-03-09 13:33:05 +01:00
Pau Perez
c19c22cb17 Apply couple simple tweaks to seeds.rb 2018-03-09 13:20:35 +01:00
Pau Pérez Fabregat
b5a8df00dd Merge pull request #2117 from coopdevs/confirm-example-user
Automatically confirm the spree@example.com user
2018-03-09 07:24:40 +01:00
Enrico Stano
0aacb91f50 Merge pull request #2116 from coopdevs/clean-sample-data
Clean sample data
2018-03-07 20:58:30 +01:00
Pau Perez
1b39d57800 Remove deprecated reference to Spree::MailMethod
Said class is removed in https://github.com/spree/spree/pull/2643 in
Spree.
2018-03-07 16:24:39 +01:00
Pau Perez
5eb3dc4beb Bring states.yml from l10n_au
The states.yml present in this repo had a different format which doesn't
work with the current seeds.rb that we brought from ofn-install.
2018-03-07 10:30:12 +01:00
Pau Perez
9849f76c1c Bring seeds.rb from ofn-install 2018-03-07 10:28:34 +01:00
Pau Perez
ae2eba89ca Automatically confirm the spree@example.com user
This allows you to log in with it after you run `bundle exec
openfoodnetwork:dev:load_sample_data` rake task right away.
2018-03-07 10:10:38 +01:00
Rob H
dadbb7445b Merge pull request #2110 from oeoeaio/subs-summary-hash
Subs: Fix summary emails for shop owners
2018-03-07 16:41:38 +11:00
Rob H
4fd307832e Merge pull request #2120 from oeoeaio/subs-unpause-messaging
Subs: messaging around unpausing a subscription
2018-03-07 16:41:00 +11:00
Rob Harrington
09ca9ac2dd Alter scope to return both completed and resumed orders 2018-03-07 14:24:59 +11:00
Rob Harrington
b98afc00ba Show message about resumable orders when unpausing a subscription 2018-03-07 14:24:59 +11:00
Rob Harrington
7332e21013 Make InfoDialog more flexible (can show information as well as errors) 2018-03-07 14:24:58 +11:00
Rob Harrington
5cb0a1c371 Fix position of jQuery dialogs in admin section 2018-03-07 14:24:58 +11:00
Pau Perez
10d6a29503 Move service class to its own file 2018-03-06 15:30:25 +01:00
Pau Perez
e06af77420 Move from hash rocket to symbol syntax 2018-03-06 13:46:32 +01:00
Pau Pérez Fabregat
392d0de6c5 Merge pull request #2055 from HugsDaniel/1766_entreprise_registration_scroll_on_first_step
Changed bootstrap grid for medium size and above to have text and but…
2018-03-06 11:39:35 +01:00
Pau Pérez Fabregat
0fdd7dabd4 Merge pull request #2026 from Matt-Yorkley/uk/embedded_headers
Only include one host in embedded shopfront headers
2018-03-06 11:07:32 +01:00
Pau Pérez Fabregat
c999627d28 Merge pull request #2114 from ltrls/fix-old-rspec-syntax
Fix old rspec syntax
2018-03-06 11:04:21 +01:00
Hugo Daniel
f2eee77a15 fixed modal height and change grid to have button and text side by side 2018-03-06 16:21:35 +11:00
Pierre de Lacroix
040c292a76 Fix some more old rspec syntax 2018-03-06 01:29:54 +01:00
Pierre de Lacroix
12e3b88b71 Fix some old Rspec syntax 2018-03-06 01:24:54 +01:00
Rob Harrington
2bfa923fe1 Use a hash instead of an array :face_palm: 2018-03-02 15:50:10 +11:00
Rob H
d30362b78c Merge pull request #2108 from oeoeaio/subs-neg-stock
Subs: handle negative stock for subscriptions
2018-03-02 15:47:12 +11:00
Rob Harrington
28491ee948 Skip stock check when requested quantity is zero
This prevents an error being raised when available stock is negative
2018-03-02 14:53:24 +11:00
Rob Harrington
fe4145d9d5 Use expect syntax 2018-03-02 14:53:24 +11:00
Rob H
3ef29fde2c Merge pull request #2107 from oeoeaio/subs-missing-close
Subs: Add message to indicate OC has no close date
2018-03-02 14:52:54 +11:00
Rob Harrington
05e6c3daa6 Add message to indicate missing orders_close_at date 2018-03-02 13:28:34 +11:00
Rob H
9d8456cbf3 Merge pull request #2090 from oeoeaio/subs-styling
Subs: Make checklist more legible
2018-03-02 13:24:05 +11:00
Rob H
1d8f332cc6 Merge pull request #2096 from oeoeaio/subs-estimates
Subs:  Improve estimates of item prices and fees
2018-03-02 13:22:27 +11:00
Rob Harrington
6f554814ce Add class documentation for SubscriptionEstimator 2018-03-02 10:11:26 +11:00
Rob Harrington
f1545a4ab6 Show fee estimates in subscription totals in UI 2018-03-02 10:11:26 +11:00
Rob Harrington
31750a7bba Add logic for calculator of fee estimates to SubscriptionEstimator 2018-03-02 10:11:26 +11:00
Rob Harrington
ad391c73ab Add migration to add fee estimate fields to subscriptions table 2018-03-02 10:11:26 +11:00
Rob Harrington
014283447d Use delegate to access subscription shop 2018-03-02 10:11:26 +11:00
Rob Harrington
3b2d4ae2d4 Estimator take variant overrides into account 2018-03-02 10:11:26 +11:00
Rob Harrington
14a03aab35 Fallback to previous saved estimate if calculator not available 2018-03-02 10:11:26 +11:00
Rob Harrington
904a364bf1 Stop unnecessarily passing fee_calculators around 2018-03-02 10:11:26 +11:00
Rob Harrington
30df1d4345 Refector controller to allow price_estimate calculation 2018-03-02 10:11:26 +11:00
Rob Harrington
b85e38010f Delegate responsibility to estimating prices for subscriptions to dedicated service object 2018-03-02 10:11:26 +11:00
Transifex-Openfoodnetwork
7a411b0452 Updating translations for config/locales/de_DE.yml 2018-03-02 03:48:06 +11:00
Transifex-Openfoodnetwork
ecbd1fe93d Updating translations for config/locales/pt.yml 2018-03-02 02:15:53 +11:00
Enrico Stano
14caac0212 Merge pull request #2074 from mjal/2057states-are-not-displayed-in-modify-address-pop-in-and-prevent-saving-2
Bug fix in customers edit address
2018-03-01 14:59:02 +01:00
Enrico Stano
6e9efe79b7 Merge pull request #2053 from Matt-Yorkley/uk/enterprise_limit
Increase default enterprise limit
2018-03-01 14:40:24 +01:00
Maxime Lalisse
cff1d7224d Bug fix in customers edit address 2018-03-01 22:02:39 +11:00
Matt-Yorkley
86a500bcdf Fix browser caching of updated icon font 2018-02-23 20:49:42 +00:00
Matt-Yorkley
7bd0de99ac Adjust brittle referer header check 2018-02-23 16:35:46 +00:00
Matt-Yorkley
9506ea456e Stub the request object instead of controller method 2018-02-23 15:57:28 +00:00
Matt-Yorkley
e173f823c8 Refactor embedded logic 2018-02-23 15:57:28 +00:00
Matt-Yorkley
4a818c07bb Only include one host in embedded shopfornt headers 2018-02-23 15:57:28 +00:00
Rob Harrington
1ac9417a20 Add class description for ProxyOrder 2018-02-22 16:23:10 +11:00
Rob Harrington
ae1c8344d1 Ensure price estimates generated for subscriptions take overrides into account 2018-02-22 16:16:49 +11:00
Rob Harrington
add9c83812 Ensure correct price is used by OrderFactory when building line items 2018-02-22 16:16:49 +11:00
Rob Harrington
993f02a989 Add knowledge of variant overrides to OrderFactory 2018-02-22 16:16:49 +11:00
Rob Harrington
d7d40a4a0f Create new OrderFactory service object for initializing order from attr hash 2018-02-22 16:16:49 +11:00
Rob Harrington
6bf4ed1ac5 Add new review view to subscription wizard 2018-02-22 16:13:29 +11:00
Rob Harrington
6bdbdc06e7 Use select2_search instead of targetted_select2_search 2018-02-22 16:13:29 +11:00
Rob Harrington
2e94654f91 Create factory to hold auxillary functions for subscriptions
NOTE: Moved estimatedSubtotal and estimatedTotal functions to the new factory from the subscription line items controller
2018-02-22 16:13:29 +11:00
Rob Harrington
2a731b2db5 Rename SubscriptionPrototype to SubscriptionActions 2018-02-22 16:13:29 +11:00
Rob Harrington
dcfa5fa42d Use services to access injected data arrays 2018-02-22 16:13:29 +11:00
Rob Harrington
ad62b258ac Populate 'all' array from Schedules#load 2018-02-22 16:13:29 +11:00
Rob Harrington
95f70409ee Auto-load customers into service when present 2018-02-22 16:13:29 +11:00
Rob Harrington
3ac57269ed Use .all convention for shipping and payment methods resource services 2018-02-22 16:13:29 +11:00
Rob Harrington
8951c79f71 Only count future orders in subs index order count 2018-02-22 15:09:33 +11:00
Rob Harrington
b3e7badd37 Fix incorrect translation key 2018-02-22 14:33:25 +11:00
Rob Harrington
cec5fddf6a Add missing translation 2018-02-22 14:33:25 +11:00
Rob Harrington
c4a81bdc48 Translate subscriptions loading flash 2018-02-22 14:33:25 +11:00
Rob Harrington
9887819c16 Update ref for ofn-qz 2018-02-22 13:56:10 +11:00
Pau Pérez Fabregat
c1b7e9f79e Merge pull request #2069 from HugsDaniel/1889_bug_in_order_cycles_filter_on_customer_admin_reports
Loads all order cycles for current user whether he is producer, distributor or coordinator
2018-02-21 17:11:52 +01:00
Hugo Daniel
3fa5ca7eae Use accessible_by method instead of involving_managed_distributors method to fetch all order cycles 2018-02-21 17:33:28 +11:00
Hugo Daniel
65fea6291e CodeClimate requested changes 2018-02-21 17:33:28 +11:00
Hugo Daniel
64c2bdda1c Added loading of all active or complete order cycles concerned by the current user to the reports form collection
User will see all order cycles he is concerned by as producer, distributor or coordinator
2018-02-21 17:33:28 +11:00
Maikel Linke
de8df4b3e9 Manual update from transifex 2018-02-21 14:25:19 +11:00
Maikel Linke
70bb64d58d Manual update from transifex 2018-02-21 14:24:45 +11:00
Maikel Linke
a529525a63 Manual update from transifex 2018-02-21 14:24:28 +11:00
Transifex-Openfoodnetwork
50c1224139 Updating translations for config/locales/de_DE.yml 2018-02-21 10:59:20 +11:00
Rob Harrington
927ab3a23a Make subscriptions setup checklist more legible 2018-02-19 11:11:10 +11:00
Pau Pérez Fabregat
183621f90b Merge pull request #2080 from coopdevs/add-skylight-staging
Enable Skylight in staging
2018-02-15 11:26:16 +01:00
Pau Perez
a7dcaf15fa Enable Skylight in staging
This is a follow-up of
https://github.com/openfoodfoundation/openfoodnetwork/pull/2070.

When running the production API key in staging, the `log/skylight.log`
showed:

```
[SKYLIGHT] [1.5.0] You are running in the staging environment but
haven't added it to config.skylight.environments, so no data will be
sent to skylight.io.
```

According to
https://www.skylight.io/support/advanced-setup#setting-up-multiple-environments
it turns out we need to create a new app for staging and use its API
key.
2018-02-14 14:46:10 +01:00
Matt-Yorkley
237854c781 Update enterprise limit error text and use expect sytnax 2018-02-13 14:05:18 +00:00
Matt-Yorkley
3c5b01ece0 Update enterprise limit spec 2018-02-13 14:05:18 +00:00
Matt-Yorkley
d52f9fd43f Add enterprise limit modal 2018-02-13 14:05:18 +00:00
Pierre de Lacroix
5c046b76f0 Fix failing tests 2018-02-13 14:05:17 +00:00
Pierre de Lacroix
ab1ed16435 Add a migration to change Spree::Users enterprise_limit default value from 1 to 5 2018-02-13 14:05:17 +00:00
Pau Pérez Fabregat
23d36e3898 Merge pull request #2058 from coopdevs/improve-order-cycle-notification
Improve code style and docs of job
2018-02-09 13:19:32 +01:00
Pau Perez
c79641c77c Fix typos in documentation 2018-02-09 09:53:40 +01:00
Pau Perez
aa4bd7f397 Improve code style and docs of job 2018-02-09 09:53:39 +01:00
Pau Pérez Fabregat
be07996656 Merge pull request #2070 from chancancode/skylight
Add Skylight instrumentation
2018-02-09 08:55:30 +01:00
Rob Harrington
e12207f3de Use shop contact email and contact name for subscription emails 2018-02-09 14:44:15 +11:00
Rob Harrington
09b800672d Fix specs to handle non-deterministic ordering 2018-02-09 14:44:15 +11:00
Rob Harrington
c59b172348 Fix typo 2018-02-09 14:44:15 +11:00
Rob Harrington
7017c8540c Replace references to 'standing line item' with 'subscription line item' 2018-02-09 14:44:15 +11:00
Rob Harrington
ae4420d9ba Rename standing line item files 2018-02-09 14:44:14 +11:00
Rob Harrington
eb53df8238 Rename 'standing_line_items' table to 'subscription_line_items' 2018-02-09 14:44:14 +11:00
Rob Harrington
71370e0bce Replace references to 'standing order' with 'subscription' (cleanup) 2018-02-09 14:44:14 +11:00
Rob Harrington
ba66c0e862 Replace references to 'standing order' with 'subscription' (schedule) 2018-02-09 14:44:14 +11:00
Rob Harrington
c605742671 Replace references to 'standing order' with 'subscription' (routes) 2018-02-09 14:44:14 +11:00
Rob Harrington
720628e49e Replace references to 'standing order' with 'subscription' (translations) 2018-02-09 14:44:14 +11:00
Rob Harrington
501fa4c901 Replace references to 'standing order' with 'subscription' (erb) 2018-02-09 14:44:14 +11:00
Rob Harrington
532f998b24 Replace references to 'standing order' with 'subscription' (js: spec) 2018-02-09 14:44:14 +11:00
Rob Harrington
b7876ebfbf Replace references to 'standing order' with 'subscription' (spec) 2018-02-09 14:44:14 +11:00
Rob Harrington
04e48989c9 Replace references to 'standing order' with 'subscription' (lib) 2018-02-09 14:44:13 +11:00
Rob Harrington
094c3e70f7 Replace references to 'standing order' with 'subscription' (HAML) 2018-02-09 14:44:13 +11:00
Rob Harrington
b3eaa30f3d Replace references to 'standing order' with 'subscription' (JS) 2018-02-09 14:44:13 +11:00
Rob Harrington
672f96b85b Replace references to 'standing order' with 'subscription' 2018-02-09 14:44:13 +11:00
Rob Harrington
902802594f Renaming standing order files (lib, spec) 2018-02-09 14:44:13 +11:00
Rob Harrington
a9b5fd69d8 Renaming standing order files 2018-02-09 14:44:13 +11:00
Rob Harrington
b258c032cc Rename 'standing_orders' table to 'subscriptions' 2018-02-09 14:44:12 +11:00
Rob Harrington
fe7b86ff60 Fix broken call to log_order which should have been record_order 2018-02-09 14:44:12 +11:00
Rob Harrington
17950ba498 Lazy load summarizers for standing order jobs outside of initializer
The enqueue script seems to causes delayed job to skip initialization of the job class, meaning that the summarizers were missing
2018-02-09 14:44:12 +11:00
Rob Harrington
ccbe33001f Add missing interpolation for shop name 2018-02-09 14:44:12 +11:00
Rob Harrington
c5f3249172 Fix rubocop issues 2018-02-09 14:44:12 +11:00
Rob Harrington
e7eb02dfe3 Reduce cognitive complexity of VariantsController#search 2018-02-09 14:44:12 +11:00
Rob Harrington
17a0b18e50 Reduce cognitive complexity of StandingLineItemsController#build 2018-02-09 14:44:12 +11:00
Rob Harrington
2012c23956 Reduce cognitive complexity of ProxyOrder#state 2018-02-09 14:44:12 +11:00
Rob Harrington
88a5d4be47 Reduce cognitive complexity of LineItemSyncer#update_item_quantities 2018-02-09 14:44:12 +11:00
Rob Harrington
224249d66b Reduce cognitive complexity of OrderSyncer 2018-02-09 14:44:11 +11:00
Rob Harrington
ceab1fe16a Reduce cognitive complexity of StandingOrderPaymentUpdater 2018-02-09 14:44:11 +11:00
Rob Harrington
c1f0a0b514 Reduce congnitive complexity of AddressFinder 2018-02-09 14:44:11 +11:00
Rob Harrington
ce09a8dad6 Reduce cognitive complexity of StandingOrder#state 2018-02-09 14:44:11 +11:00
Rob Harrington
99db6f8e14 Fix translation key for StandingOrderValidator errors 2018-02-09 14:44:11 +11:00
Rob Harrington
d6924d2866 Add comment to OrderUpdateIssues 2018-02-09 14:44:11 +11:00
Rob Harrington
3e68973812 Rename StandingOrderUpdater to OrderSyncer 2018-02-09 14:44:11 +11:00
Rob Harrington
bbc3cad67d Refactor large StandingOrderUpdater#update! method
Note: extracted line items logic into separate class
2018-02-09 14:44:11 +11:00
Rob Harrington
50d3522b2c Extract logic for recording issues with updating orders to separate class 2018-02-09 14:44:11 +11:00
Rob Harrington
2c5bfab29f Refactoring price estimation logic for StandingOrderForm 2018-02-09 14:44:11 +11:00
Rob Harrington
844cd79270 Clean-up of standing order form and spec 2018-02-09 14:44:10 +11:00
Rob Harrington
8ae4307a69 Move logic for updating orders to dedicated class 2018-02-09 14:44:09 +11:00
Rob Harrington
2c40252edb Extract validation logic for standing orders into service object 2018-02-09 14:44:09 +11:00
Rob Harrington
0c302b022a Move StandingOrderForm to app/services folder 2018-02-09 14:44:09 +11:00
Rob Harrington
7581779a0d Remove weird escape characters 2018-02-09 14:44:09 +11:00
Rob Harrington
f9727de206 Comment out interface for turning standing orders ON for an enterprise 2018-02-09 14:44:09 +11:00
Rob Harrington
76daa183d5 Add orders sub-menu to standing-order index page 2018-02-09 14:44:09 +11:00
Rob Harrington
981b874263 Remove unused method active? for order cycles 2018-02-09 14:44:09 +11:00
Rob Harrington
4362ef2cea Properly translate all error messages for StandingOrderForm 2018-02-09 14:44:09 +11:00
Rob Harrington
7ca60e1990 Use activerecord error translations properly 2018-02-09 14:44:09 +11:00
Rob Harrington
1bf2f7ad03 Fix a couple of offences pickup up by rubocop 2018-02-09 14:44:09 +11:00
Rob Harrington
8ba1a909ca Use summarizer for standing order confirm job 2018-02-09 14:44:08 +11:00
Rob Harrington
c86207212f Add confirmation summary email 2018-02-09 14:44:08 +11:00
Rob Harrington
86cddb1cc4 Capitalise translated strings 2018-02-09 14:44:08 +11:00
Rob Harrington
b49c44f7ce Generalise record_failure method to record_and_log_error 2018-02-09 14:44:08 +11:00
Rob Harrington
818af47613 Move rescue clause to process method
This prevents a placement email from being sent unless the order is processed successfully
2018-02-09 14:44:08 +11:00
Rob Harrington
ef6c9ec0f0 Integrate standing order summarizer into placement job 2018-02-09 14:44:08 +11:00
Rob Harrington
13d01df4d8 Add mail method and template for sending placement summary emails to shop owners 2018-02-09 14:44:08 +11:00
Rob Harrington
cf30b7c883 Add service objects for summarizing outcomes of standing order processing jobs 2018-02-09 14:44:08 +11:00
Rob Harrington
0c0e12e165 Show edit link in placement email if changes are allowed by shop 2018-02-09 14:44:08 +11:00
Rob Harrington
f9af8edf27 Ignore Metrics/BlockLength for specs and Rails/HasAndBelongsToMany 2018-02-09 14:44:08 +11:00
Rob Harrington
8bf460c93a Manually fix remaining rubocop offences 2018-02-09 14:44:08 +11:00
Rob Harrington
f902b8cef0 Fix rubocop Style/ClassAndModuleChildren offences 2018-02-09 14:44:07 +11:00
Rob Harrington
84ad996ef8 Use guard clauses 2018-02-09 14:44:07 +11:00
Rob Harrington
fb28940952 Use Time.zone.now instead of Time.now 2018-02-09 14:44:07 +11:00
Rob Harrington
03f1980b1b Auto-correct rubocop offences for standing-orders 2018-02-09 14:44:07 +11:00
Rob Harrington
26a325e6e0 Handle payment processing errors for standing orders 2018-02-09 14:44:07 +11:00
Rob Harrington
2576d10e49 Create a new payment when none is present 2018-02-09 14:44:07 +11:00
Rob Harrington
67e05cea9c Add failed payment email to StandingOrderMailer 2018-02-09 14:44:07 +11:00
Rob Harrington
0ccb0ce0e4 Make standing order header partial more generic 2018-02-09 14:44:07 +11:00
Rob Harrington
8c96a19e3e Specify minimum postgresql version for travis 2018-02-09 14:44:07 +11:00
Rob Harrington
6e83c6dc86 Move standing order emails to a dedicated StandingOrderMailer 2018-02-09 14:44:07 +11:00
Rob Harrington
d6a9d63de5 Replace StandingOrderSyncJob with ProxyOrderSyncer service object 2018-02-09 14:44:06 +11:00
Rob Harrington
6ea343f26e Clean up proxy order performance specs 2018-02-09 14:44:06 +11:00
Rob Harrington
43c2aca208 Use delete_all instead of destroy_all for increased speed 2018-02-09 14:44:06 +11:00
Rob Harrington
8a498391ca Add performance spec for removal of proxy orders 2018-02-09 14:44:06 +11:00
Rob Harrington
146348a4fe Refactor proxy order syncer using direct sql query for increased speed 2018-02-09 14:44:06 +11:00
Rob Harrington
48b39f4712 Add performance spec for proxy order syncer 2018-02-09 14:44:06 +11:00
Rob Harrington
3aee0b5e70 Allow proxy order syncer to accept both ActiveRecord::Relation or StandingOrder 2018-02-09 14:44:06 +11:00
Rob Harrington
6d5c920a95 Split proxy order sync logic out into dedicated service object 2018-02-09 14:44:06 +11:00
Rob Harrington
cdf04323a9 Serialize standing order credit_card_id to enable selection in edit form 2018-02-09 14:44:06 +11:00
Rob Harrington
bdac68900f Move address and card loading logic down into DetailsController
Also switch to using CreditCardResource to load the card
2018-02-09 14:44:05 +11:00
Rob Harrington
a5ae4c801c Initialize ofn-select2 with empty array when data is a promise 2018-02-09 14:44:05 +11:00
Rob Harrington
404913dcfa Move form-saving logic into dedicated StandingOrderForm service 2018-02-09 14:44:05 +11:00
Rob Harrington
c94badbf36 Stub or provide mailer as appropriate 2018-02-09 14:44:04 +11:00
Rob Harrington
ca1485f121 Add missing translations for proxy order controller error messages 2018-02-09 14:44:04 +11:00
Rob Harrington
dfe874cf3f Attempt to add a credit card before processing payment 2018-02-09 14:44:04 +11:00
Rob Harrington
c20c9e2e78 Use the rails logger instead of Bugsnag 2018-02-09 14:44:04 +11:00
Rob Harrington
f4f6fb6a7a Update and process standing order payments prior to confirmation 2018-02-09 14:44:04 +11:00
Rob Harrington
ac8e09bc11 Add credit card validation to StandingOrderForm 2018-02-09 14:44:04 +11:00
Rob Harrington
183ad87d07 Fix mislabeled StandingOrderForm specs 2018-02-09 14:44:04 +11:00
Rob Harrington
f95d1ef058 Show message when no credit cards available for a customer 2018-02-09 14:44:04 +11:00
Rob Harrington
61b64a7516 Add credit card selection element to standing orders form 2018-02-09 14:44:04 +11:00
Rob Harrington
494f2f4821 Add cards lookup action to CustomersController 2018-02-09 14:44:04 +11:00
Rob Harrington
d3937e5c80 Move customer address lookup action to CustomersController 2018-02-09 14:44:03 +11:00
Rob Harrington
3ac2ac34ed Add credit_card_id to StandingOrder model 2018-02-09 14:44:03 +11:00
Rob Harrington
25907d8969 Prevent standing order form from accepting non cash/stripe payment methods 2018-02-09 14:44:03 +11:00
Rob Harrington
26b85052e1 Load only Cash and Stripe payment methods into standing order form actions 2018-02-09 14:44:03 +11:00
Rob Harrington
07a7993109 Require a Cash or Stripe payment method in standing order setup process 2018-02-09 14:44:03 +11:00
Rob Harrington
7798b12086 Replace translation key for yes_i_am_sure 2018-02-09 14:44:03 +11:00
Rob Harrington
be11a1a2f9 Fix memoization issue with line item unit specs 2018-02-09 14:44:03 +11:00
Rob Harrington
86d8133f82 Stop setting host for url helpers in specs
All configuration is now happening in test.rb or spec_helper.rb
2018-02-09 14:44:03 +11:00
Rob Harrington
6081db382c Updating addresses on standing order updates addresses on any initialised orders 2018-02-09 14:44:03 +11:00
Rob Harrington
b89ab2c407 Adding link to view/edit the order from Standing Order placement and confirmation emails 2018-02-09 14:44:02 +11:00
Rob Harrington
fce2d743e5 Adding proxy-order state to specs 2018-02-09 14:44:02 +11:00
Rob Harrington
2a3fc8cfec Automatically copy shipping address from billing if none present 2018-02-09 14:44:02 +11:00
Rob Harrington
7d1fc8cbe1 Make sure correct intro message is used for empty standing order notification 2018-02-09 14:44:02 +11:00
Rob Harrington
f969caa2d1 Do not place standing order when no items are available
Send notification to customer informing them that an order was not placed...
2018-02-09 14:44:02 +11:00
Rob Harrington
0fd86a6cc7 Adding UI to require action from user when pausing/cancelling standing order with open orders 2018-02-09 14:44:02 +11:00
Rob Harrington
ab5dc7ddd5 Require action from user when pausing/cancelling standing order with open orders 2018-02-09 14:44:02 +11:00
Rob Harrington
3ce8a1abba Tweaking proxy order state logic
Inherits 'paused' state from standing order if present
2018-02-09 14:44:02 +11:00
Rob Harrington
834e5b702e Using standing_order_form.$submitted for show/hide logic for angularjs form errors 2018-02-09 14:44:02 +11:00
Rob Harrington
001f329393 Refactoring StandingOrderPrototype
Allow handling of create/update responses from downstream controllers using promise chaining
2018-02-09 14:44:01 +11:00
Rob Harrington
72549697a3 Redirecting to standing orders index on successful standing order save 2018-02-09 14:44:01 +11:00
Rob Harrington
1e0356a74b StatusMessages can be shown on StandingOrder index 2018-02-09 14:44:01 +11:00
Rob Harrington
42266397aa Improving performance of available variant lookup for standing orders
Only search the DB for available variants once
2018-02-09 14:44:01 +11:00
Rob Harrington
846cccf373 Showing StandingOrder error messages in status bar when save fails 2018-02-09 14:44:01 +11:00
Rob Harrington
ad2506fe75 Require StandingOrders to have at least one product (StandingLineItem) 2018-02-09 14:44:01 +11:00
Rob Harrington
7dcd39986f Refactoring StandingOrder validations and errors
Moving validations to StandingOrderForm
2018-02-09 14:44:01 +11:00
Rob Harrington
b28f2908a6 Fix 'postcode' typo in standing order form 2018-02-09 14:44:01 +11:00
Rob Harrington
7d9d510c0f Adding a comma after each schedule listed on OC index 2018-02-09 14:44:01 +11:00
Rob Harrington
c64f3590ad Using placeholder attribute to show prompt text for schedule dropdown 2018-02-09 14:44:01 +11:00
Rob Harrington
f0f478dfa0 Adding placeholder field with default to ofn-select2 component 2018-02-09 14:44:00 +11:00
Rob Harrington
ceaae89dee Prevent order cycles that are linked to schedules from being destroyed 2018-02-09 14:44:00 +11:00
Rob Harrington
77a50eac42 Show confirmation message when creating/updating/deleting Schedules 2018-02-09 14:44:00 +11:00
Rob Harrington
877a5f27d1 ProxyOrder state is 'pending' until OC opens, then 'cart' until OC closes 2018-02-09 14:44:00 +11:00
Rob Harrington
2c0928ca20 Automatically show 'Schedules' column on OC index when Standing Orders are enabled 2018-02-09 14:44:00 +11:00
Rob Harrington
4e686ecfcc Debouncing admin variant search requests by 300ms 2018-02-09 14:44:00 +11:00
Rob Harrington
35e42b28fe Using customer selection to search for addresses on standing order creation
Can also copy copy address from billing to shipping
2018-02-09 14:44:00 +11:00
Rob Harrington
9137f68a57 Adding logic to SearchController#customer_addresses for case when customer is not found 2018-02-09 14:44:00 +11:00
Rob Harrington
6ac49a7694 Adding route and controller action for searching for customer addresses using AddressFinder 2018-02-09 14:44:00 +11:00
Rob Harrington
c5066bb613 Making AddressFinder a little more secure
Only allow search by email when a customer or user with matching email is also provided
2018-02-09 14:43:59 +11:00
Rob Harrington
4a0dab3608 Renaming LastUsedAddress as AddressFinder 2018-02-09 14:43:59 +11:00
Rob Harrington
1b72b7258d Refactoring LastUsedAddress to take customers or users 2018-02-09 14:43:58 +11:00
Rob Harrington
58070a8b3e Adding loading flash and no-results messaging to standing orders index 2018-02-09 14:43:58 +11:00
Rob Harrington
57653cb911 Displaying setup instructions on Standing Orders index 2018-02-09 14:43:58 +11:00
Rob Harrington
ae209f72b9 Removing unrequired OrderCycleOpenCloseJob 2018-02-09 14:43:58 +11:00
Rob Harrington
2859075e43 WIP: StandingOrderConfirmJob no longer scoped to an order cycle 2018-02-09 14:43:58 +11:00
Rob Harrington
0e50009875 WIP: StandingOrderPlacementJob no longer scoped to an order cycle 2018-02-09 14:43:58 +11:00
Rob Harrington
514a462f7b WIP: Refactor, of standing order placement and confirmation jobs
ie. Transfering responsibility for tracking standing order placement and confirmation to proxy orders
2018-02-09 14:43:58 +11:00
Rob Harrington
01cbd7ae9d WIP: Adding flags for standing order placement and confirmation to proxy_orders table 2018-02-09 14:43:58 +11:00
Rob Harrington
f92b824f52 User is warned about initialising standing order orders 2018-02-09 14:43:58 +11:00
Rob Harrington
3adfb0db3f Issues with updating orders are reported when saving standing orders 2018-02-09 14:43:58 +11:00
Rob Harrington
fd07830c02 Adding order_update_issues to serialized proxy orders 2018-02-09 14:43:57 +11:00
Rob Harrington
9e986f25f1 Orders are not marked as problematic if the changed value matches the new value 2018-02-09 14:43:57 +11:00
Rob Harrington
e357a7b401 StandingOrderForm: Storing problematic orders for reporting to user 2018-02-09 14:43:57 +11:00
Rob Harrington
9f50253537 StandingOrderForm: Rescuing from RecordInvalid when saving 2018-02-09 14:43:57 +11:00
Rob Harrington
1e8767e8b5 StandingOrderForm: Small refactor, update initialised orders one-by-one 2018-02-09 14:43:57 +11:00
Rob Harrington
a6add2eff6 Limiting shops loaded onto standing orders index to those with standing orders enabled 2018-02-09 14:43:57 +11:00
Rob Harrington
25639a822a Implementing standing order feature toggle on back-end interface 2018-02-09 14:43:57 +11:00
Rob Harrington
e1f8af6d5b Adding standing orders feature toggle to enterprise form 2018-02-09 14:43:57 +11:00
Rob Harrington
e7b8648792 Adding standing orders feature toggle column to enterprises table 2018-02-09 14:43:57 +11:00
Rob Harrington
c819197d07 BasicOrderCycleSerializer serialises open and closes dates with time and zone 2018-02-09 14:43:57 +11:00
Rob Harrington
15fb493d9a StandingOrderPlacementJob: cap quantity at 0 for items not available through OC 2018-02-09 14:43:56 +11:00
Rob Harrington
cd6394987d StandingOrderPlacementJob: Moving logic for processing an order to completion to separate method 2018-02-09 14:43:56 +11:00
Rob Harrington
0cf7d1a63d Link standing order orders to user on initialisation if customer user exists 2018-02-09 14:43:56 +11:00
Rob Harrington
439c81d836 Format of hours in standing order placement email without leading zero 2018-02-09 14:43:56 +11:00
Rob Harrington
1e0d43e975 Changing explain text on confirm email
Removing mention of making changes
2018-02-09 14:43:56 +11:00
Rob Harrington
994baf12c4 Adding specs to ensure placement emails are sent 2018-02-09 14:43:56 +11:00
Rob Harrington
d12a1371c2 Assigning a priority to OrderCycleOpenCloseJob 2018-02-09 14:43:56 +11:00
Rob Harrington
f9e40ba586 Fixing typos in standing order placement job 2018-02-09 14:43:56 +11:00
Rob Harrington
a32fb752dd Removing number column from orders panel, adding edit action 2018-02-09 14:43:56 +11:00
Rob Harrington
e4f30cea57 Fixing styling for table rows within index panels 2018-02-09 14:43:56 +11:00
Rob Harrington
d0f4cc2ee2 PlacementJob loads ProxyOrders based on order cycle close date 2018-02-09 14:43:55 +11:00
Rob Harrington
c4c9c92d7e Refactoring StandingOrderPlacementJob, loading ProxyOrders and initialsing where necessary 2018-02-09 14:43:55 +11:00
Rob Harrington
e6fbdb17e8 Only initialise a proxy order once 2018-02-09 14:43:55 +11:00
Rob Harrington
02f474e16a Fixing up spec data for orders spec 2018-02-09 14:43:55 +11:00
Rob Harrington
0861a4391e Removing ui-sortable library (no longer required) 2018-02-09 14:43:55 +11:00
Rob Harrington
1731d4daa7 Rejigging schedule dialog, limit options to coordinated order cycles, with same coordinator as selected OCs 2018-02-09 14:43:55 +11:00
Rob Harrington
875557dc9d WIP: ProxyOrders don't require an order, fixing remainder of specs 2018-02-09 14:43:55 +11:00
Rob Harrington
be8fa1f4e4 WIP: ProxyOrders don't require an order, calculating total for serialized proxy orders from standing order where order does not exist 2018-02-09 14:43:55 +11:00
Rob Harrington
3d3013a592 WIP: ProxyOrders don't require an order, adding an edit path for proxy orders
initialises an order if one does not exist and redirects to its edit path
2018-02-09 14:43:55 +11:00
Rob Harrington
4b440c83a4 WIP: ProxyOrders don't require an order, StandingOrderForm changes 2018-02-09 14:43:55 +11:00
Rob Harrington
f57cae9124 Removing null: false contraint on order_id for ProxyOrder 2018-02-09 14:43:55 +11:00
Rob Harrington
2231d4c6cf Using factories to build spec data rather than StandingOrderForm 2018-02-09 14:43:54 +11:00
Rob Harrington
e29a4f9a8a Moving order initialisation logic from StandingOrderForm to ProxyOrder model 2018-02-09 14:43:54 +11:00
Rob Harrington
64206bc35b ProxyOrders belong to order cycles 2018-02-09 14:43:54 +11:00
Rob Harrington
e351c3e355 Renaming StandingOrderOrder to ProxyOrder 2018-02-09 14:43:54 +11:00
Rob Harrington
fc845a36f1 Fix weird spec failure cause by a Rails.cache.clear call resetting the currency to USD on CI only 2018-02-09 14:43:54 +11:00
Rob Harrington
9bf3767093 Preventing line item stock level checks when updating standing orders 2018-02-09 14:43:54 +11:00
Rob Harrington
8e0f2fcb35 Adding optional manual override of line item stock level check 2018-02-09 14:43:54 +11:00
Rob Harrington
00ee5a63df Removing incorrect namespacing from StandingOrderForm spec 2018-02-09 14:43:54 +11:00
Rob Harrington
e068c4831b Adding job to send confirm emails for standing orders on order cycle close 2018-02-09 14:43:54 +11:00
Rob Harrington
2a03477597 Adding standing_orders_confirmed_at flag to order_cycles 2018-02-09 14:43:54 +11:00
Rob Harrington
deebc31c34 DRYing out standing order email template 2018-02-09 14:43:53 +11:00
Rob Harrington
9f1ff1fd01 Adding OrderCycleOpenCloseJob to the whenever schedule 2018-02-09 14:43:53 +11:00
Rob Harrington
f7229ab229 Uninitialised but recently updated order_cycles also trigger StandingOrderPlacementJob 2018-02-09 14:43:53 +11:00
Rob Harrington
c2b68ed6b5 Running StandingOrderSyncJob when order cycles added to a schedule via OrderCyclesController 2018-02-09 14:43:53 +11:00
Rob Harrington
0a74bb8373 Running StandingOrderSyncJob when order cycles added to a schedule via SchedulesController 2018-02-09 14:43:53 +11:00
Rob Harrington
ef5ff3a663 Adding job to re-sync standing orders when order cycles are added to or removed from schedules 2018-02-09 14:43:53 +11:00
Rob Harrington
d6e5c0b346 Adding extra scopes to StandingOrder model 2018-02-09 14:43:53 +11:00
Rob Harrington
107474fc74 Fixing standing_order_with_items factory 2018-02-09 14:43:53 +11:00
Rob Harrington
9a984963a7 Ensuring that only active standing orders are processed when order cycle opens 2018-02-09 14:43:53 +11:00
Rob Harrington
805baa18a9 Adding cancel/close button to standing order form 2018-02-09 14:43:53 +11:00
Rob Harrington
533b05384c Refactoring save bar on standing order create/edit form 2018-02-09 14:43:52 +11:00
Rob Harrington
9c2e67e953 Cancelling a standing order just changes the state, does not remove it from the page 2018-02-09 14:43:52 +11:00
Rob Harrington
522e646b36 Adding tooltips to standing order index actions 2018-02-09 14:43:52 +11:00
Rob Harrington
3d8dceb76a Displaying state of standing orders on index 2018-02-09 14:43:52 +11:00
Rob Harrington
b9316422d2 Adding method to determine state of standing orders 2018-02-09 14:43:52 +11:00
Rob Harrington
8d1899b13d Adding pause and unpause actions to standing orders 2018-02-09 14:43:52 +11:00
Rob Harrington
8ff9ffbc38 Adding controller actions and routes for pausing and unpausing a standing order 2018-02-09 14:43:52 +11:00
Rob Harrington
961df756c5 Adding paused_at column to standing orders 2018-02-09 14:43:52 +11:00
Rob Harrington
736de4826f Renaming cancelled_at column to canceled_at, for consistency 2018-02-09 14:43:52 +11:00
Rob Harrington
774245f540 Adding cancel button to standing orders index 2018-02-09 14:43:51 +11:00
Rob Harrington
a2ddf78842 Ensure red buttons have white text 2018-02-09 14:43:51 +11:00
Rob Harrington
f4ce0a4b81 Adding ConfirmDialog service 2018-02-09 14:43:51 +11:00
Rob Harrington
a23a0a233e Renaming info dialog stylesheet to more general dialogs.css 2018-02-09 14:43:51 +11:00
Rob Harrington
7dcf7ec5b0 Adding controller action and route for cancelling a standing order 2018-02-09 14:43:51 +11:00
Rob Harrington
b643829fe2 Standing Orders can be marked as cancelled 2018-02-09 14:43:51 +11:00
Rob Harrington
076a05f8a9 Adding spec for case when standing_order_orders aren't linked to an order cycle
This should never happen, but came up in specs
2018-02-09 14:43:50 +11:00
Rob Harrington
284103b6b6 Adding canceled_at column to standing_orders table 2018-02-09 14:43:50 +11:00
Rob Harrington
dd099eae54 Visualising standing order order state, still some spec failures 2018-02-09 14:43:50 +11:00
Rob Harrington
309781d5b1 Individual StandingOrder orders can be resumed from Standing Order index 2018-02-09 14:43:50 +11:00
Rob Harrington
2023a1a2fc Adding translations for StandingOrderOrder resume/cancel errors 2018-02-09 14:43:50 +11:00
Rob Harrington
d1ca9a6e14 Adding a #resume action to StandingOrderOrdersController 2018-02-09 14:43:49 +11:00
Rob Harrington
fc463fd608 Adding resume logic to StandingOrderOrder model 2018-02-09 14:43:49 +11:00
Rob Harrington
d89a05aec8 Adding an error message when cancellation of standing order order fails 2018-02-09 14:43:49 +11:00
Rob Harrington
6dd31a947e Show closing times for orders in standing order orders panel 2018-02-09 14:43:49 +11:00
Rob Harrington
5191877fbe BasicOrderCycleSerializer renders order open and close times 2018-02-09 14:43:49 +11:00
Rob Harrington
f6af5098b0 Using MomentJS to handle dates on bulk order management 2018-02-09 14:43:48 +11:00
Rob Harrington
7644f08d5c Individual StandingOrder orders can be cancelled from Standing Order index 2018-02-09 14:43:48 +11:00
Rob Harrington
27b22acd37 Fixing bug that caused references to stale DOM objects to be kept and used by Panels service
Was causing panels to break when used in conjuction with ng-repeat + filters
2018-02-09 14:43:48 +11:00
Rob Harrington
50b84c4ced Fixing typo in SO spec description 2018-02-09 14:43:48 +11:00
Rob Harrington
9160a3ff6b Displaying Order Cycle names in orders panel on standing orders index 2018-02-09 14:43:48 +11:00
Rob Harrington
a57815edbb Refactoring standing line item delete logic
Using StandingOrderForm rather than separate endpoint
2018-02-09 14:43:47 +11:00
Rob Harrington
4c754e2cdb Ensuring that new standing_line_items are added to orders and totals are updated 2018-02-09 14:43:47 +11:00
Rob Harrington
fcf2681abc WIP: Adding basic order panel to standing order index 2018-02-09 14:43:47 +11:00
Rob Harrington
ffcffb30ca Moving standing orders products panel template into separate partial 2018-02-09 14:43:47 +11:00
Rob Harrington
cdff1ef7b6 TEMP: Adding scopes for standing_order_orders 2018-02-09 14:43:47 +11:00
Rob Harrington
d95d9df0f1 Standing Order Orders can be cancelled 2018-02-09 14:43:47 +11:00
Rob Harrington
56fb50f644 Refactoring customer_search_override directive
Passing distributor_id into isolate scope, rather than pulling from separate element
2018-02-09 14:43:47 +11:00
Rob Harrington
f4cbd90400 Storing estimated prices for standing line items in the database 2018-02-09 14:43:46 +11:00
Rob Harrington
9baaf1efc9 Only running StandingOrder service 'after' callbacks for known standing orders
ie. those in byID or pristineByID
2018-02-09 14:43:46 +11:00
Rob Harrington
0196218d06 Conditionally loading an edit path for standing orders
ie. only if they have an id
2018-02-09 14:43:46 +11:00
Rob Harrington
b253373d4d Styling save button for standing order panels, and updating pristineByID array on update/save 2018-02-09 14:43:46 +11:00
Rob Harrington
8f71b56c26 Using same serializer for standing order index and edit pages 2018-02-09 14:43:46 +11:00
Rob Harrington
e8ee1dad04 Building params for adding new customer in the dialog directive, rather than generic Customers service 2018-02-09 14:43:45 +11:00
Rob Harrington
dc2551d881 Moving Schedules and ScheduleResource services to admin.resources module 2018-02-09 14:43:45 +11:00
Rob Harrington
c167780cad Adding auto-loading of schedules to Schedules service via constructor 2018-02-09 14:43:45 +11:00
Rob Harrington
534e69fde5 Including errors attribute from StandingOrderPrototype in spec 2018-02-09 14:43:45 +11:00
Rob Harrington
e92b17a341 Adding an error message when attempting to add duplicate variant to a standing order 2018-02-09 14:43:45 +11:00
Rob Harrington
1bd01c83a7 WIP: Adding panel for editing items to standing order index 2018-02-09 14:43:44 +11:00
Rob Harrington
05bc2bd293 All methods on StandingOrder service are instance methods, StandingOrders service loads instances of StandingOrder 2018-02-09 14:43:44 +11:00
Rob Harrington
6f4c9070f6 Adding StandingLineItemsController to handle addition and removal of SLIs from standing orders 2018-02-09 14:43:44 +11:00
Rob Harrington
198f63d0b3 Removing unrequired StatusMessage injection 2018-02-09 14:43:44 +11:00
Rob Harrington
a72da7036b buildItem and removeItem are instanceMethods standingOrder objects 2018-02-09 14:43:44 +11:00
Rob Harrington
3571b8c5fa Fixing date specification for order cycle spec 2018-02-09 14:43:43 +11:00
Rob Harrington
91a2274fe5 Adding link and dialog for creating a new standing order 2018-02-09 14:43:43 +11:00
Rob Harrington
0f2adaa8d2 Adding link to standing orders index to orders sub-menu 2018-02-09 14:43:43 +11:00
Rob Harrington
c3e071b0d1 Removing retry from stabilised customers codes feature spec 2018-02-09 14:43:43 +11:00
Rob Harrington
8c9765749e Ensuring that backorders are disabled when testing quantity capping for standing orders 2018-02-09 14:43:43 +11:00
Rob Harrington
6cf23b46c5 Fixing broken country and state selection for customer addresses 2018-02-09 14:43:42 +11:00
Rob Harrington
7fa55fe5c6 Adding spec to ensure that invalid changes to standing orders are not propagated to associated orders 2018-02-09 14:43:42 +11:00
Rob Harrington
21d8aafd97 Using numbers for state and countries ids in AddressSerializer 2018-02-09 14:43:42 +11:00
Rob Harrington
fbd3d99b1b OC feature spec: Using find for columns dropdown instead of first 2018-02-09 14:43:42 +11:00
Rob Harrington
f14c36ed6b Sending placement email when standing order order in placed on OC open 2018-02-09 14:43:42 +11:00
Rob Harrington
65db856054 Order confirmation emails are not sent for standing order orders. 2018-02-09 14:43:42 +11:00
Rob Harrington
8ab698d4dc Generating orders for standing orders ignores stock on hand at initialisation 2018-02-09 14:43:42 +11:00
Rob Harrington
5598a0d24f line_item.unit_value delegates to variant when quantity is 0 or final_weight_volume is missing 2018-02-09 14:43:41 +11:00
Rob Harrington
ef00dca5a0 Changing format of changes object in standing order placement job 2018-02-09 14:43:41 +11:00
Rob Harrington
7a308f1651 Updating letter_opener gem 2018-02-09 14:43:41 +11:00
Rob Harrington
3edfd07a40 WIP: adding method to StandingOrderPlacementJob to send emails 2018-02-09 14:43:41 +11:00
Rob Harrington
5e0186fa1f Standing Order Placement Job: capping line items quantities to available stock level 2018-02-09 14:43:41 +11:00
Rob Harrington
1c7e9923f9 Checking for sufficient stock takes variant overrides into account 2018-02-09 14:43:41 +11:00
Rob Harrington
a8928a0ccc Capping line item quantity at stock takes overrides into account 2018-02-09 14:43:40 +11:00
Rob Harrington
2aad722b4b WIP, SO placement job: preventing payments on standing orders from being processed when OC opens 2018-02-09 14:43:40 +11:00
Rob Harrington
9ad6dce2d6 WIP, SO placement job: processing orders to completion 2018-02-09 14:43:39 +11:00
Rob Harrington
178aadb311 WIP, SO placement job: Finding orders to be placed 2018-02-09 14:43:39 +11:00
Rob Harrington
6f629e112a WIP, OC open-close job: performing the job spawns StandingOrderPlacementJobs for each recently opened OC 2018-02-09 14:43:39 +11:00
Rob Harrington
5b25f63e44 WIP, OC open-close job: finding recently opened order cycles 2018-02-09 14:43:39 +11:00
Rob Harrington
140d62939a Adding processing marker column standing_orders_placed_at to order cycles 2018-02-09 14:43:39 +11:00
Rob Harrington
95a7fc8ef5 Initialisation and removal of standing order orders respects begins_at and ends_at contraints 2018-02-09 14:43:39 +11:00
Rob Harrington
3eff65f1f5 Finish refactoring of Standing Order Updaters, replacing with form class used by controller 2018-02-09 14:43:38 +11:00
Rob Harrington
2a3dc33f86 WIP: Pushing shipment and payment update logic down into separate methods 2018-02-09 14:43:38 +11:00
Rob Harrington
6ea4aac361 WIP: Refactoring StandingOrderUpdater into StandingOrderForm
Update logic coupled to update action on controller rather than changes to the model
2018-02-09 14:43:38 +11:00
Rob Harrington
0b35cb6619 Standing Order Updater handles changes to line item quantities 2018-02-09 14:43:38 +11:00
Rob Harrington
9468dcb406 Adding lib class to maintain standing order orders 2018-02-09 14:43:38 +11:00
Rob Harrington
d5349e7ad0 Standing Orders: adding association between orders and standing orders 2018-02-09 14:43:38 +11:00
Rob Harrington
a7132684e5 Standing Orders: create join table for linking orders with standing orders 2018-02-09 14:43:37 +11:00
Rob Harrington
7eac6e725a Standing Orders: adding order_cycles association to StandingOrder model 2018-02-09 14:43:37 +11:00
Rob Harrington
aeae0f245e Standing Orders: standing line items can be deleted from existing standing order 2018-02-09 14:43:37 +11:00
Rob Harrington
38d75d2b1c Standing Orders: adding routing and controller action for deleting standing line items 2018-02-09 14:43:37 +11:00
Rob Harrington
594bec1b37 StandingLineItems can be removed when creating a StandingOrder 2018-02-09 14:43:37 +11:00
Rob Harrington
1b711bcd46 Standing Orders can be edited 2018-02-09 14:43:37 +11:00
Rob Harrington
4ad6b1a65e Billing and Shipping addresses can be set on new standing orders 2018-02-09 14:43:37 +11:00
Rob Harrington
b701ca43f4 WIP: adding shiping and billing address to StandingOrder model 2018-02-09 14:43:37 +11:00
Rob Harrington
88563431b8 Module arguments passed to injection functions in consistent way 2018-02-09 14:43:36 +11:00
Rob Harrington
06fffb9ef7 SO Index: centering data in some columns 2018-02-09 14:43:35 +11:00
Rob Harrington
ab0728cd0b SO Index: Adding day to standing order dates 2018-02-09 14:43:35 +11:00
Rob Harrington
44d7537744 SO Index: Adding items column 2018-02-09 14:43:34 +11:00
Rob Harrington
6fadeacf0e SO Index: Adding begins_on and ends_on columns 2018-02-09 14:43:34 +11:00
Rob Harrington
af9376b60c SO Index: Adding column dropdown 2018-02-09 14:43:34 +11:00
Rob Harrington
a395f183f9 SO Index: adding spec for changing shops 2018-02-09 14:43:34 +11:00
Rob Harrington
7c57d3d4c6 SO Index: standing orders can be filtered using quick search 2018-02-09 14:43:34 +11:00
Rob Harrington
bbd43f7026 SO Index: User must select a shop first in order to load relevant standing orders 2018-02-09 14:43:34 +11:00
Rob Harrington
a94742e4db Ensuring ransack restrictions are applied in StandingOrderController#collection 2018-02-09 14:43:33 +11:00
Rob Harrington
24cb823c90 Loading managed shops into standing orders index, to be used for filtering 2018-02-09 14:43:33 +11:00
Rob Harrington
8372317a8f Enterprise User can view basic listing of standing orders 2018-02-09 14:43:33 +11:00
Rob Harrington
ef08fd4bb3 Adding dedicated standing order serializer for index 2018-02-09 14:43:33 +11:00
Rob Harrington
1d58ef55f7 Calling Standing Orders index controller action using json returns serialized data 2018-02-09 14:43:33 +11:00
Rob Harrington
a1ccf8a28e Adding initial defaults for standing orders index column visibility 2018-02-09 14:43:32 +11:00
Rob Harrington
7ab05cf857 Basic AngularJS controller and service for loading StandingOrders 2018-02-09 14:43:32 +11:00
Rob Harrington
c18c1c67d1 Adding visibility permissions for standing orders 2018-02-09 14:43:32 +11:00
Rob Harrington
cd2d73810d StandingOrderResource can handle index action 2018-02-09 14:43:32 +11:00
Rob Harrington
91917886a8 Adding basic routing and templates for standing orders index 2018-02-09 14:43:32 +11:00
Rob Harrington
8bbc0b7790 Adding translations to standing order form 2018-02-09 14:43:32 +11:00
Rob Harrington
2e83ab80cf Tweaking layout of details section of standing order creation form 2018-02-09 14:43:32 +11:00
Rob Harrington
bba4b54f9b Adding a wizard progress indicator to standing order creation form 2018-02-09 14:43:31 +11:00
Rob Harrington
897eb11512 Standing Orders: form split into ngForm elements with staggered validation 2018-02-09 14:43:31 +11:00
Rob Harrington
ac5fe6a9fb Each section of standing order form has a title 2018-02-09 14:43:31 +11:00
Rob Harrington
29760d6419 Renaming 'items' partial as 'products' 2018-02-09 14:43:31 +11:00
Rob Harrington
1808e3881f Making standing order creation more like a wizard 2018-02-09 14:43:31 +11:00
Rob Harrington
a9ea042791 Splitting details section of standing order form out into partial 2018-02-09 14:43:31 +11:00
Rob Harrington
6d5ca1501c Moving standing order form into separate partial 2018-02-09 14:43:31 +11:00
Rob Harrington
946046e53b Moving action for estimating standing_line_item prices into StandingLineItemController#build 2018-02-09 14:43:31 +11:00
Rob Harrington
71b84d490e Adding validation contraints to standing order associations 2018-02-09 14:43:30 +11:00
Rob Harrington
6bd5a895b3 Moving InfoDialog into admin.utils module 2018-02-09 14:43:30 +11:00
Rob Harrington
e661430cc9 StandingLineItems added to StandingOrder are saved
Adding some additional validation
2018-02-09 14:43:30 +11:00
Rob Harrington
415955e7b3 SO: Adding variants to a new standing order, price estimate provided 2018-02-09 14:43:30 +11:00
Rob Harrington
5aa993f5b4 Moving select2 config for variant-autocomplete into a directive 2018-02-09 14:43:30 +11:00
Rob Harrington
6934b87816 SO: Adding basic interface for Standing Order creation 2018-02-09 14:43:29 +11:00
Rob Harrington
e4de7e262d SO: Adding StandingLineItem model 2018-02-09 14:43:29 +11:00
Rob Harrington
d711c321b6 SO: Adding Standing Order Model 2018-02-09 14:43:29 +11:00
Rob Harrington
733dc76c6c Order Cycles can be assigned to schedules via new/edit form 2018-02-09 14:43:29 +11:00
Rob Harrington
4195bd6cd8 Order Cycles can be filtered by Schedule 2018-02-09 14:43:29 +11:00
Rob Harrington
8c0bad3115 Schedules can be deleted from OC index 2018-02-09 14:43:28 +11:00
Rob Harrington
a9b9cbf4bd Restoring 'Loading' flash to order cycle index 2018-02-09 14:43:28 +11:00
Rob Harrington
33e5601658 Adding translation for schedule without OCs error 2018-02-09 14:43:28 +11:00
Rob Harrington
2a1ca1c206 Using angular-ui sortable instead of pure jQuery, refactoring logic around including blanks in select2s 2018-02-09 14:43:28 +11:00
Rob Harrington
357040f67a Enterprise User can create and update schedules via OC index 2018-02-09 14:43:28 +11:00
Rob Harrington
920f52e112 Adding schedules to Order Cycles interface 2018-02-09 14:43:28 +11:00
Rob Harrington
a25f2141a5 Adding Order Cycle Schedules join table 2018-02-09 14:43:27 +11:00
Rob Harrington
c51b956b01 Adding Schedule model 2018-02-09 14:43:27 +11:00
Rob Harrington
0d845b0fd6 Adding column toggling interface to Order Cycles index 2018-02-09 14:43:27 +11:00
Rob Harrington
fe9f147ff0 Adding ability to filter OC index by OC name or 'involved' enterprise 2018-02-09 14:43:27 +11:00
Rob Harrington
2a5f598fb0 Angularising Order Cycles Index 2018-02-09 14:43:20 +11:00
Maxime Lalisse
bf69ed0008 Add and namespace a missing translation key 2018-02-09 11:57:44 +11:00
Maxime Lalisse
8bd952ed56 Add i18n for defaced elements in admin_product_tabs 2018-02-09 11:57:44 +11:00
Maxime Lalisse
9a3f61904b Add translation keys for admin_product_tabs 2018-02-09 11:57:44 +11:00
Godfrey Chan
fbc5318a7b Add Skylight instrumentation
If you’re not already familiar with [Skylight](https://www.skylight.io),
it is a smart profiler for Rails apps. Skylight makes it easy to
pinpoint performance issues in Rails applications.

We work on a lot of open source projects ourselves, and in our
experience it can be pretty hard to get contributors to work on
application performance issues. Few contributors consider working
on performance problems, and the ones that might be interested may
not even know where to start.

By making performance information more accessible, we hope to
inspire potential contributors to tackle slow parts of your app,
and have a good way to see if their contributions helped.

Local deployments that are interested in this can request an API
token from https://www.skylight.io/oss and set it in
`config/application.yml` (if no token is set, it will log a message to
`log/skylight.log` but won't otherwise prevent the app from working
normally).
2018-02-07 11:37:30 -08:00
Matt-Yorkley
41ce7047cc Tidy up order cycle spec 2018-02-07 17:48:16 +11:00
Matt-Yorkley
f28471e456 Fixed datepicker button intermittent failure 2018-02-07 17:48:16 +11:00
Matt-Yorkley
4cb9e3a3f1 Datepicker CSS tweaks 2018-02-07 17:48:16 +11:00
Matt-Yorkley
2f6a249b5f Fix missing datepicker icon 2018-02-07 17:48:16 +11:00
Pau Perez
0634735288 Adjust Codeclimate config to ignore Rails patch
Since it is a file copied from Rails 4, we want to keep it in its
original state and not refactor it.
2018-02-07 16:21:16 +11:00
Pau Perez
719c45b408 Apply Rails 4 patch at boot time not only specs
This makes this patch available also for things like database-related
rake tasks. It moves the patch to an initializer.
2018-02-07 16:21:16 +11:00
Maikel Linke
b70edd5424 Enabling non-privileged postgres users to run specs
Addressing issue #245.

A combination of fixtures and foreign key constraints requires the postgres
user to be superuser. Otherwise an attempt to disable constraints fails.
This got fixed in Rails 4 and this patch brings the same behaviour back to
Rails 3. It will allow us to run the specs with a nosuperuser postgres user.

See:
 - https://github.com/matthuhiggins/foreigner/issues/61
 - 9bb27f7ffe
2018-02-07 16:21:16 +11:00
Aaron Hursh
a6498c2f96 Removed ng-disabled conditional from submit button on admin customers index. 2018-02-07 15:09:07 +11:00
Rob Harrington
56be7b1d46 Fix spec to handle non-deterministic ordering 2018-02-07 11:45:48 +11:00
Rob Harrington
b2f3477261 Change unused creation_date translation key back to confirmation_date
See 22eae753fe for original change
2018-02-07 11:42:38 +11:00
Matt-Yorkley
14b73149be Remove stale form validation messages when showing new confirmation sent message 2018-02-07 10:41:54 +11:00
Matt-Yorkley
0ab7d95607 Remove mention of confirmation email from enterprise creation wizard 2018-02-07 10:41:53 +11:00
Matt-Yorkley
ee08dcfeb4 Use owner as contact if user record doesn't exist 2018-02-07 10:41:53 +11:00
Matt-Yorkley
b893dea810 Make sure userSelect directive uses our Admin::UserSerializer instead of base Spree api view 2018-02-07 10:41:53 +11:00
Matt-Yorkley
ec5ce45850 Change confirmation email wording 2018-02-07 10:41:53 +11:00
Matt-Yorkley
9afb97fa0f Show contact email without full permissions 2018-02-07 10:41:53 +11:00
Matt-Yorkley
676abe0ced Remove serialized contact attributes 2018-02-07 10:41:53 +11:00
Matt-Yorkley
73d38cb91b Re-add text version of confirmation email for accessibility 2018-02-07 10:41:53 +11:00
Matt-Yorkley
fffae46a63 Remove enterpriseRoles from enterprsies controller 2018-02-07 10:41:53 +11:00
Matt-Yorkley
6ed91cab1f Remove old translation keys 2018-02-07 10:41:53 +11:00
Matt-Yorkley
cc5d0c35dd Refactor enterprise contact user assignment 2018-02-07 10:41:53 +11:00
Matt-Yorkley
c34570154c Use contact model in printed tickets 2018-02-07 10:41:53 +11:00
Matt-Yorkley
a5940e1641 Fix user controller spec 2018-02-07 10:41:53 +11:00
Matt-Yorkley
39f0c5b5b0 Rename contact name field and revert contact name specs 2018-02-07 10:41:53 +11:00
Matt-Yorkley
abb5adec43 Enterprise managers UI specs 2018-02-07 10:41:53 +11:00
Matt-Yorkley
525cb4826f Code review refactoring 2018-02-07 10:41:53 +11:00
Matt-Yorkley
fde0aba96c Feedback when user changes email addess 2018-02-07 10:41:53 +11:00
Matt-Yorkley
ff18fd25f1 Adjust Discourse login for user confirmations 2018-02-07 10:41:53 +11:00
Matt-Yorkley
9248ac05ac Adjustments for failing specs 2018-02-07 10:41:53 +11:00
Matt-Yorkley
a066c6391d Adjust injection data namespacing 2018-02-07 10:41:53 +11:00
Matt-Yorkley
4d11485283 Use receives_notifications flag for enterprise contact 2018-02-07 10:41:53 +11:00
Matt-Yorkley
9e270690ef Remove enterprise email
A user with the same email address is receiving notifications now.
If the email address is invalid, the owner receives notifications.
2018-02-07 10:41:53 +11:00
Matt-Yorkley
15b781b271 Update enterprise managers and contact role 2018-02-07 10:41:52 +11:00
Matt-Yorkley
5dc8f21b7b Show confirmed status in enterprise managers UI 2018-02-07 10:41:52 +11:00
Matt-Yorkley
9ccb3ee80b Add receives_notifications flag to enterprise_roles 2018-02-07 10:41:52 +11:00
Matt-Yorkley
27de66b055 Owner's permissions can't be deleted 2018-02-07 10:41:52 +11:00
Matt-Yorkley
ba98c7e2c5 Rewrite enterprise contact functionality 2018-02-07 10:41:52 +11:00
Matt-Yorkley
22eae753fe Remove enterprise confirmations 2018-02-07 10:41:52 +11:00
Pierre de Lacroix
d832d850fe Revert removed translations for Enterprise mails 2018-02-07 10:41:52 +11:00
Matt-Yorkley
aead867ea0 Set all current users to confirmed 2018-02-07 10:41:51 +11:00
Matt-Yorkley
97f5022bdd Show signup message in modal wihout redirect 2018-02-07 10:41:51 +11:00
Matt-Yorkley
0cb7a555d3 Adjust confirmation template 2018-02-07 10:41:51 +11:00
Maikel Linke
52b7872a55 Simplify conditionals 2018-02-07 10:41:51 +11:00
Matt-Yorkley
522aaee1a3 Update login modal for resending confirmations 2018-02-07 10:41:51 +11:00
Matt-Yorkley
179cf6e484 Tidy up confirmation migrations 2018-02-07 10:41:51 +11:00
Matt-Yorkley
28ded1f0c2 Adjust user signup feedback 2018-02-07 10:41:51 +11:00
Pierre de Lacroix
7d971fc39d Add UserConfirmationsController spec 2018-02-07 10:41:51 +11:00
Pierre de Lacroix
4f0b20e8ad Better tests 2018-02-07 10:41:51 +11:00
Pierre de Lacroix
a6f2ee1367 Add migration to confirm already confirmed email addresses 2018-02-07 10:41:51 +11:00
Pierre de Lacroix
eb1c598a6c Fix tests 2018-02-07 10:41:51 +11:00
Pierre de Lacroix
4706bf0528 Remove changes on FR locale file 2018-02-07 10:41:51 +11:00
Matt-Yorkley
969b6caa96 Code cleanup 2018-02-07 10:41:51 +11:00
Matt-Yorkley
69ea1e6d26 Set test users to confirmed by default 2018-02-07 10:41:51 +11:00
Pierre de Lacroix
91704d9df7 Create user confirmation email 2018-02-07 10:41:51 +11:00
Pierre de Lacroix
dbbc2ddb1c Add confirmable email to user model 2018-02-07 10:41:51 +11:00
Pau Pérez Fabregat
99729457cc Merge pull request #2063 from coopdevs/autocorrect-cop
Autocorrect rubocop Layout/BlockEndNewline cop
2018-02-05 08:50:58 +01:00
Pau Pérez Fabregat
5a58294bc6 Merge pull request #2042 from erose357/master
addresses issue #1275
2018-02-02 13:41:23 +01:00
Enrico Stano
398b3bbd8b Merge pull request #1960 from coopdevs/remove-warning
Fix payment_method_decorator boot-time warning
2018-02-02 10:43:51 +01:00
Pau Perez
6cb038c362 Autocorrect rubocop Layout/BlockEndNewline cop 2018-02-01 09:52:53 +01:00
Pau Pérez Fabregat
cc40948783 Merge pull request #2051 from coopdevs/regenerate-knapsack-report
Regenerate Knapsack report
2018-01-31 15:04:30 +01:00
Enrico Stano
00bdcd3948 Merge pull request #2045 from coopdevs/use-symbol-hash-syntax
Enable HashSyntax rubocop cop with symbol style
2018-01-31 09:30:06 +01:00
Matt-Yorkley
c860ffc176 Adjust use of non-translatable open/closed icons 2018-01-24 15:33:26 +11:00
Pau Perez
8664411880 Disable knapsack report generation again
No need to enable it to regenerate the report again until Knapsack
itself tells us.
2018-01-23 09:21:56 +01:00
Pau Perez
f17f1008e3 Update knapsack report file with latest CI values 2018-01-23 09:21:10 +01:00
Pau Perez
a2828f3b9a Regenerate Knapsack report
It's already asking for it in the CI output
2018-01-23 08:06:53 +01:00
Pau Perez
cbfdfb43e3 Enable HashSyntax rubocop cop with symbol style
This enforces the ruby 1.9 symbol hash syntax and consistency among the
style of the keys.

  # bad
  {:a => 1, :b => 2}
  {c: 2, 'd' => 3} # should just use hash rockets

  # good
  {a: 1, b: 2}
  {:c => 3, 'd' => 4}

The .rubocop-todo.yml is also updated to keep track of the existing
violations.
2018-01-20 12:50:50 +01:00
Matt-Yorkley
23e672aef9 Add updated globe icon to mobile view 2018-01-19 10:56:11 +00:00
Matt-Yorkley
6d9cc7e29d Fix account page locale 2018-01-18 10:22:40 +11:00
Matt-Yorkley
8a47788a09 Remake OFN icon font 2018-01-18 10:22:40 +11:00
Matt-Yorkley
afed5ab666 Refector spec 2018-01-18 10:22:40 +11:00
Matt-Yorkley
357eda8c19 Adjustments for failing specs 2018-01-18 10:22:40 +11:00
Matt-Yorkley
f18401d183 Language switcher frontend 2018-01-18 10:22:40 +11:00
Matt-Yorkley
4ea91d14f9 Template I18n changes 2018-01-17 12:03:27 +11:00
Pau Perez
f57661b13f Fix payment_method_decorator boot-time warning
Removes the annoying message "warning: already initialized constant
Spree::PaymentMethod::DISPLAY" that appears 4 times when booting the
app.

We are declaring said constant exactly as our Spree version does so
there's no point on repeating work.
2018-01-15 12:50:05 +01:00
Pau Pérez Fabregat
ad25c1d1b2 Merge pull request #2033 from coopdevs/add-setup-script
Add setup script
2018-01-15 12:05:19 +01:00
Pau Perez
87af5dcee5 Point to rbenv and nodenv from setup script
Show the appropriate links when the Ruby and Node dependencies are not
met. This will make it easier for newcomers to install them.
2018-01-12 08:22:50 +01:00
Pau Perez
106871b956 Check node version and install npm packages 2018-01-11 14:14:08 +01:00
Pau Perez
4d25abcfce Add setup script
It aims to aid new open source contributors on setting up their dev
env by means of a single command with meaningful output.

Although ofn-install ansible scripts also work for development we don't
want to add too much burden to those single-time beginner contributions.
2018-01-11 14:14:08 +01:00
Rob Harrington
2ccdf3c97a Use upstream and origin as remote names
Also fixed a couple of typos
2018-01-11 14:30:08 +11:00
Rob Harrington
89bd9c8038 Update CONTRIBUTIONS.md to reflect current processes 2018-01-11 14:30:08 +11:00
Enrico Stano
88627dc837 Merge pull request #2038 from boveus/master
Update README.md
2018-01-10 12:17:21 +01:00
Brandon Stewart
8ca57b0705 Update README.md 2018-01-09 14:02:27 -07:00
Brandon Stewart
c7db283e8c Update README.md 2018-01-09 14:00:07 -07:00
erose357
83ca3b7b8b Adds a css rule to target the logo in .footer-local and padding between the logo and open source info at the bottom 2018-01-09 12:54:41 -07:00
Brandon Stewart
830699d2b8 Update README.md 2018-01-09 10:29:02 -07:00
Brandon Stewart
f822e658c4 Update README.md 2018-01-09 10:23:51 -07:00
Brandon Stewart
8817a1afb7 Update README.md 2018-01-09 10:23:30 -07:00
Brandon Stewart
693adf181e Update README.md 2018-01-09 10:21:24 -07:00
Brandon Stewart
f269f13b09 Update README.md 2018-01-08 11:50:44 -07:00
Matt-Yorkley
9845258a25 Merge pull request #2035 from Matt-Yorkley/uk/rubocop_fix
Update rubocop.yml
2018-01-05 20:16:44 +00:00
Enrico Stano
edbed2c8d3 Merge pull request #1984 from coopdevs/fix/api-key-taxons
Disable api auth as there is no Spree api key set
2018-01-05 10:31:36 +01:00
Matt-Yorkley
8e0f2d2500 Merge pull request #2037 from Matt-Yorkley/uk/codeclimate_checks
Codeclimate yml update
2018-01-05 01:37:06 +00:00
Matt-Yorkley
e022504c26 Codeclimate yml update 2018-01-04 17:10:55 +00:00
Matt-Yorkley
62e4cbd052 Update rubocop.yml 2018-01-04 16:01:06 +00:00
Enrico Stano
70ae59550d Merge pull request #2032 from Matt-Yorkley/uk/codeclimate_migrations
Adjust codeclimate engine for migrations folder
2018-01-03 13:48:47 +01:00
Lynne
f74af8fa2d Merge pull request #2034 from lin-d-hop/translations-uk
Manual uk translation update
2018-01-03 06:00:07 +01:00
lin-d-hop
82d1b57005 Not updated from transifex so manually commiting 2018-01-03 03:40:04 +00:00
Lynne
c32aacc1b3 Delete en-GB.yml
Superseded by en_GB.yml
2018-01-03 03:29:52 +00:00
Matt-Yorkley
523b4045bf Adjust codeclimate engine for migrations folder 2018-01-02 13:54:41 +00:00
Enrico Stano
8e4e273b7c Merge pull request #1994 from openfoodfoundation/transifex
Transifex
2017-12-22 16:36:44 +11:00
Enrico Stano
816297e22f Merge pull request #2022 from ltrls/add-order-print-ticket-feature-test
Add feature test for the Spree::Admin::OrdersController print_ticket action
2017-12-22 15:07:17 +11:00
Pau Perez
72889b5c36 Stub current_user instead of api key's user 2017-12-21 10:24:29 +11:00
Pau Perez
0f0216fe79 Upgrade spree to get our latest patch 2017-12-21 10:24:29 +11:00
Pierre de Lacroix
42433d1ad4 Add feature test for the Spree::Admin::OrdersController print_ticket action 2017-12-20 23:01:18 +01:00
Pau Perez
52533fc04c Rely on Spree's default value for requires_auth 2017-12-20 17:25:23 +11:00
Pau Perez
bb0223877c Remove unused arguments and reduce object creation 2017-12-20 17:25:23 +11:00
Pau Perez
5eb1fcddbb Remove dependency on TestingSupport by inlining 2017-12-20 17:25:23 +11:00
Pau Perez
c646eb3939 Disable api auth as there is no Spree api key set
Although Spree::Api::Config[:requires_authentication] is set to false by
default for some unknown reason if not done explicitly Spree still
returns it as false.

This amends the change done in a87c89c83d,
which introduced the bug. As there is no Spree api key set the auth
fails when getting taxons.
2017-12-20 17:25:23 +11:00
Enrico Stano
a313c99370 Merge pull request #2005 from coopdevs/upgrade-spree-fork-version
Upgrade spree's fork to latest commit
2017-12-20 17:23:48 +11:00
Enrico Stano
0f84d9f02e Merge pull request #2004 from coopdevs/is-this-needed
Remove unused Enterprise scopes
2017-12-20 16:59:15 +11:00
Enrico Stano
900a9c6145 Merge pull request #2000 from coopdevs/issue-template-improvement
Mention screenshot in the issue template
2017-12-20 16:48:54 +11:00
Pau Perez
5b33cbe9aa Upgrade spree's fork to latest commit
Needed to get
3289b5e31c
2017-12-20 16:37:14 +11:00
Enrico Stano
114ce3b764 Merge pull request #1940 from coopdevs/improve-readability-shop
Improve readability of shop's code
2017-12-20 16:28:53 +11:00
Enrico Stano
660d3f326f Remove unused Enterprise scopes 2017-12-20 16:00:35 +11:00
Pau Perez
b8d51ae0de Mention screenshot in the issue template
For things like translations it's enough sharing a screenshot when
reporting a bug. See
https://github.com/openfoodfoundation/openfoodnetwork/issues/1999
2017-12-20 10:16:53 +11:00
Enrico Stano
0bdda6387a Merge pull request #1996 from coopdevs/add-issue-template
Create issue template
2017-12-19 18:00:04 +11:00
Pau Perez
4fbdbb1aa2 Link to placeholder feature template
We'll write the template later on
2017-12-19 15:26:21 +11:00
Pau Perez
72ddcb4fff Create issue template
It assumes most of the times issues will be reported to keep track of
bugs.
2017-12-19 11:07:29 +11:00
Transifex-Openfoodnetwork
50ef2de5f9 Updating translations for config/locales/fr.yml 2017-12-15 20:06:43 +11:00
Transifex-Openfoodnetwork
55d3ee1af0 Updating translations for config/locales/pt.yml 2017-12-13 21:19:42 +11:00
Transifex-Openfoodnetwork
422166441e Updating translations for config/locales/en_US.yml 2017-12-09 02:29:48 +11:00
Transifex-Openfoodnetwork
9d3f85628c Updating translations for config/locales/nb.yml 2017-12-08 18:44:22 +11:00
Pierre de Lacroix
669d9c3c66 Fix translations on account page 2017-12-06 15:21:19 +11:00
Enrico Stano
dcb406d246 Merge pull request #1986 from andypalmer/github_protocol_warning
Change github definition to remove insecure protocol warning.
2017-12-04 21:49:05 +11:00
Andy Palmer
cadad28b0c Change github definition to remove insecure protocol warning. Consistently use 1.9.3 hash syntax 2017-12-04 16:50:36 +11:00
Enrico Stano
01b0a033fd Merge pull request #1904 from oeoeaio/spree-test-config
Use Spree's approach for preventing config caching when testing
2017-12-04 15:57:11 +11:00
Pierre de Lacroix
0fb66ab258 Fix CodeClimate issues 2017-12-01 13:37:30 +11:00
Pierre de Lacroix
a49c21cfd1 Add instance switch to enable number localization 2017-12-01 13:37:24 +11:00
Pierre de Lacroix
f67a8c1f2d Add tests 2017-12-01 13:37:24 +11:00
Pierre de Lacroix
f4624ead42 Make all products reload when updating in bulk edit 2017-12-01 13:37:24 +11:00
Pierre de Lacroix
2cd570383f Use localize_number in models 2017-12-01 13:37:24 +11:00
Pierre de Lacroix
920900b619 Add Spree::LocalizedNumber module 2017-12-01 13:37:24 +11:00
Pau Perez
e98d934a67 Include localization files as documented in gem
I followed the Usage help in
https://github.com/derekprior/momentjs-rails.
2017-11-29 10:13:05 +11:00
leandroalemao
31a846b9c3 Refactor _i18n_script.html.haml file and add new momentjs internationalisation files 2017-11-29 10:13:05 +11:00
leandroalemao
5eaea28401 Switch momentjs internationalisation according to I18n locale 2017-11-29 10:13:05 +11:00
Pierre de Lacroix
50ef902adb Add missing tooltip in products' bulk edit page 2017-11-23 11:31:41 +11:00
Pierre de Lacroix
75b6a078c6 Add missing translation 2017-11-23 11:31:41 +11:00
Pierre de Lacroix
c0c93c172e Add tooltips in products bulk edit page 2017-11-23 11:31:41 +11:00
Pau Perez
ed18244070 Remove TODO in favour of an issue in Github
It has become the issue
https://github.com/openfoodfoundation/openfoodnetwork/issues/1961
2017-11-23 11:12:17 +11:00
Pierre de Lacroix
e13063e0c6 Fix before_filter for Spree::Admin::OrdersController#print_ticket 2017-11-23 11:01:41 +11:00
Rob Harrington
6c38997010 Fix 1664: product tag rules not working
Caused by a combination of: fe7bd5e2cd and 38d3b446cc

Have added/tweaked specs to prevent this from happening again
2017-11-15 10:26:24 +11:00
Pau Perez
0e01c0d69b Turn TODO into issue #1957
TODOs that live in the code can't be prioritized and tend to be
forgotten.
2017-11-15 09:44:11 +11:00
Pau Perez
caab3ea74d Add spree user as admin of Enterprise 2 in seed 2017-11-15 09:42:21 +11:00
Lynne
c543dff2e1 Merge pull request #1956 from coopdevs/improve-pr-template
Add special keyword syntax to close issue from PR
2017-11-14 14:16:08 +01:00
Pau Perez
92badfd88c Add special keyword syntax to close issue from PR
We want the issue to be closed when the PR gets merged but we always
forget to add the "magic" comment as described in
https://help.github.com/articles/closing-issues-using-keywords/.
2017-11-14 09:02:52 +01:00
Lynne
dca64e6939 Merge pull request #1944 from lin-d-hop/master
Adding UK About pages to menus
2017-11-10 16:33:58 +01:00
Saimon Moore
a9c4d27d5e Undo i18n_fallbacks change to production.rb 2017-11-10 12:30:24 +11:00
Saimon Moore
610c2f9519 Ensure en is an I18n fallback in all environments
Since `en` is considered as the main fallback for all locales
ensure that it is present in all environments.

Note: Setting `config.i18n.fallbacks` to `true` means use the default locale
which means that if a particular instance is not using an `en` based locale
(the parent `en` locale is automatically derived as a fallback) then `en` will
not be available as a fallback.
2017-11-10 12:30:24 +11:00
Saimon Moore
05d757e7c4 Ensure we have min i18n fallbacks
This setting defines which locales will be exported to the frontend.
In general, ofn currently functions under a single locale
(which is also the default locale) but all translations are made from
the `en` locale.

The current process of ensuring translations are translated and make
their way into code is manual and prone to issues so occasionally
translations for keys in the default locale of a particular instance
are not deployed and the UI displays `missing translation` messages.

In these cases, it is far friendlier for the user to see fallbacks to
`en` rather than these errors so this commit ensure that at the very
least apart from the current default locale, `en` is also made available
and as such will be exported to the frontend so that it's translations
are available as a fallback in JS land.

I18n fallback config was already enabled in both frontend and backend.
Until now, available locales may not have been set (determined by the
`AVAILABLE_LOCALES` env var) and the translations for `en` not therefore
be present in the frontend for fallback to actually work.

This commit will ensure that a fallback to `en` is always possible in the
case of missing translations.
2017-11-10 12:30:24 +11:00
Maxim Colls
31a2453882 Bootstrap angular module in new_variant form 2017-11-10 09:37:36 +11:00
Rob Harrington
5febd0a0d6 Restructure flaky customer spec 2017-11-10 08:47:12 +11:00
Rob Harrington
694f1e9b25 Update knapsack report 2017-11-10 08:47:12 +11:00
Andy Palmer
131bf842a9 Update matchers to non-deprecated protocol 2017-11-10 08:47:12 +11:00
Andy Palmer
8ec1c2e04a No longer use expensive page.evaluate_script for imperative methods 2017-11-10 08:47:12 +11:00
Andy Palmer
e94dc257a1 We actually need to restart the driver, not the session 2017-11-10 08:47:12 +11:00
Andy Palmer
3bd4fc59d4 We reset the phantom js driver after each context to prevent it memory leaking and dying 2017-11-10 08:47:12 +11:00
Andy Palmer
7b8463b03a PhantomJS no longer crashes due to too specific selector 2017-11-10 08:47:12 +11:00
Rob Harrington
00e7fc1c0d Bump capybara version 2017-11-10 08:47:12 +11:00
Rob Harrington
2ca20ad701 Bump poltergeist version to 1.16.0 2017-11-10 08:47:12 +11:00
Maikel Linke
775da82072 Add waiting conditions to spec 2017-11-10 08:47:12 +11:00
Maikel Linke
162b392004 Use expect syntax, correct spec description 2017-11-10 08:47:12 +11:00
Maikel Linke
26bedf0523 Make title matcher more robust 2017-11-10 08:47:12 +11:00
Maikel Linke
ff3ee62509 Remove old comment 2017-11-10 08:47:12 +11:00
Maikel Linke
9c2a78adf2 Avoid warnings, use expect syntax 2017-11-10 08:47:12 +11:00
Maikel Linke
5a767ba3ef Avoid warning, use new syntax 2017-11-10 08:47:12 +11:00
Rob Harrington
691d642721 Use url helper instead of string to define expected url 2017-11-10 08:47:12 +11:00
Rob Harrington
7dbfc3740d Revert "Add workaround to pass Spree core tests in Travis"
This reverts commit 9cdec737078caa6eb5a90480cabb6ca477ab597b.
2017-11-10 08:47:12 +11:00
Rob Harrington
b2897d7feb Reset Spree::Config.allow_backorders to original value in spec 2017-11-10 08:47:12 +11:00
Julius Pabrinkis
b18177c215 Add workaround to pass Spree core tests in Travis 2017-11-10 08:47:12 +11:00
Julius Pabrinkis
cec0a8c2e7 Specify page object for Capybara#find methods 2017-11-10 08:47:12 +11:00
Julius Pabrinkis
412de318ed Manually disable backorders in failing features 2017-11-10 08:47:12 +11:00
Julius Pabrinkis
92cc7a4648 Another try for failing feature 2017-11-10 08:47:12 +11:00
Julius Pabrinkis
96c0481e17 Fix intermittently failing product distribution feature 2017-11-10 08:47:12 +11:00
Julius Pabrinkis
5dd7ddc288 Refactor base controller with new rspec syntax 2017-11-10 08:47:12 +11:00
Julius Pabrinkis
ea91a82f30 Try to fix shopping cart failing feauture in Travis 2017-11-10 08:47:12 +11:00
Julius Pabrinkis
8e10269b50 Try to fix intermittently failing test for product distribution 2017-11-10 08:47:12 +11:00
Julius Pabrinkis
dae74666c5 Add missing 'type: :request' for request spec 2017-11-10 08:47:12 +11:00
Julius Pabrinkis
94e31e35ba Fix Spree::Admin::BaseController related issues 2017-11-10 08:47:12 +11:00
Rob Harrington
c835b4eb1a Replacing stub_model objects with actual factory generated instances 2017-11-10 08:47:12 +11:00
Rob Harrington
ef9e43fbd3 Replacing mock_model objects with instance_doubles 2017-11-10 08:47:12 +11:00
Rob Harrington
f083433854 Explicitly specifying 'type: :helper' for all helper specs 2017-11-10 08:47:12 +11:00
Rob Harrington
9052b1c3db A few updates to spec where 'be true' and 'be false' didn't cut it 2017-11-10 08:47:12 +11:00
Rob Harrington
59578a73af Changing all references to 'be_true' and 'be_false' to 'be true' and 'be false'
See next commit for changes where this substitution was broken
2017-11-10 08:47:12 +11:00
Rob Harrington
c691e260cf Rspec matcher enqueue_job for Delayed::Job supports block expectations 2017-11-10 08:47:12 +11:00
Rob Harrington
82072c8970 Explicitly specifying 'type: :controller' for all controller specs 2017-11-10 08:47:12 +11:00
Rob Harrington
d0c52ac176 Updating outdated guard gems 2017-11-10 08:47:12 +11:00
Rob Harrington
6811a62568 Updating RSpec Gems 2017-11-10 08:47:12 +11:00
Buildkite
8653d03969 Merge remote-tracking branch 'origin/master' into HEAD 2017-11-09 13:49:39 +00:00
lin-d-hop
90d5a04368 Adding UK About pages to menus 2017-11-09 11:06:58 +00:00
Pau Perez
84e4ebef08 Do not notify Bugsnag of a cache miss
It's not the responsibility of a error tracking software to track
neither cache misses nor logs. That is what log monitoring is for.
2017-11-09 10:22:31 +01:00
Pau Perez
98603c4042 Do not test private methods 2017-11-09 10:22:31 +01:00
Pau Perez
26a4ee0171 Do not stub object under test 2017-11-09 10:22:31 +01:00
Pau Perez
4f03a2d25c Remove unnecessary require 2017-11-09 10:22:31 +01:00
Pau Perez
6a830a3843 Isolate ArraySerializer case in injection helper
This makes this special case with the ArraySerializer stand out so that
the reader notices it.
2017-11-09 10:22:30 +01:00
Pau Perez
3ffd049135 Remove commented out code 2017-11-09 10:22:30 +01:00
Rob Harrington
e6d1b38b82 Remove upgrade_bundler script by reverting 250062bd2, 3f2299e52 and 5dfac10599 2017-11-09 19:46:41 +11:00
Rob Harrington
f8a892faf2 Remove upgrade_bundler script by reverting 250062bd2, 3f2299e52 and 5dfac10599 2017-11-09 18:24:22 +11:00
Pierre de Lacroix
54e141489a Add noindex meta tag for invisible shops and staging environment 2017-11-09 12:04:27 +11:00
Pau Perez
e64fd1d308 Lower log level in prod to :info so we can debug
Otherwise, there are no log lines for any request, which makes it
impossible to find out anything about the app in production.

Obviously this increases the size of the log files but this has to be
  dealt with log rotation. The data is our most important asset.
2017-11-09 11:13:32 +11:00
Matt-Yorkley
01647c3df9 Disable allow_backorders by default in test environment 2017-11-02 17:43:46 +11:00
Rob Harrington
cd6d7c76f6 Fix spec that requires preference persistence 2017-11-02 17:43:04 +11:00
Rob Harrington
efa71c4ac8 Use Spree's approach for handling config when testing 2017-11-02 17:43:04 +11:00
Rob Harrington
d4eb27a4ed Fix race condition in shipping method order spec 2017-11-01 16:37:12 +11:00
Duende13
eca18ba6ee Test to control order of shipping methods by name 2017-11-01 15:30:42 +11:00
Duende13
31fa49feed Added orderBy 'name' to the list of shipping methods offered. 2017-11-01 15:30:42 +11:00
yasirazgar
b68aafdb72 1799 - adding missing translations in new shipping methods page 2017-11-01 10:50:21 +11:00
Andy Palmer
fd09a63e48 Imperative specs as per review comments 2017-10-24 17:56:04 +11:00
Andy Palmer
afc50863cd Replace Deface with update to overridden template 2017-10-24 17:39:34 +11:00
Andy Palmer
fea2240c39 Disabled product links in cart for openfoodfoundation/openfoodnetwork#1075 2017-10-24 14:56:35 +11:00
570 changed files with 20187 additions and 3382 deletions

View File

@@ -1,14 +1,36 @@
engines:
version: "2"
plugins:
rubocop:
enabled: true
channel: rubocop-0-48
channel: "rubocop-0-48"
scss-lint:
enabled: false
ratings:
paths:
- app/**
- lib/**
- "**.rb"
exclude_paths:
- spec/**/*
- vendor/**/*
duplication:
enabled: true
exclude_patterns:
- "db/**"
- "config/initializers/active_record_postgresql_referential_integrity_patch.rb"
checks:
argument-count:
enabled: false
complex-logic:
enabled: true
file-lines:
enabled: false
method-complexity:
enabled: false
method-count:
enabled: false
method-lines:
enabled: false
nested-control-flow:
enabled: true
return-statements:
enabled: true
similar-code:
enabled: true
identical-code:
enabled: true
exclude_patterns:
- "spec/**/*"
- "vendor/**/*"

42
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,42 @@
<!--- If what you want to file is not a bug, please use the [Feature
template](https://github.com/openfoodfoundation/openfoodnetwork/wiki/Feature-template)
instead -->
<!--- Provide a general summary of the issue in the Title above -->
## Description
<!--- Provide a more detailed introduction to the issue itself, and why you consider it to be a bug -->
## Expected Behavior
<!--- Tell us what should happen -->
## Actual Behavior
<!--- Tell us what happens instead -->
## Steps to Reproduce
<!--- Provide an unambiguous set of steps to reproduce this bug -->
<!--- Include code to reproduce, if relevant -->
1.
2.
3.
4.
## Animated Gif/Screenshot
<!-- Provide a screenshot or brief animated gif reproducing the bug. Linux users can use
[Peek](https://github.com/phw/peek#ubuntu) while Mac users can use [Recordit](http://recordit.co/) -->
## Context
<!--- How has this bug affected you? What were you trying to accomplish? -->
## Severity
<!--- Use the [Bug severity
guideline](https://github.com/openfoodfoundation/openfoodnetwork/wiki/Bug-severity) to assign one to this bug -->
## Your Environment
<!--- Include as many relevant details about the environment you experienced the bug in -->
* Version used:
* Browser name and version:
* Operating System and version (desktop or mobile):
## Possible Fix
<!--- Not obligatory, but suggest a fix or reason for the bug -->

View File

@@ -1,5 +1,7 @@
#### What? Why?
Closes #[the issue number this PR is related to]
[Explain why is this change needed and the solution you propose. Provide
context for others to understand it]

View File

@@ -27,6 +27,10 @@ Style/Documentation:
Style/StringLiterals:
Enabled: false
Style/HashSyntax:
Enabled: true
EnforcedStyle: ruby19_no_mixed_keys
Layout/MultilineMethodCallIndentation:
Enabled: true
EnforcedStyle: indented
@@ -53,6 +57,10 @@ Lint/UselessAssignment:
Rails/DynamicFindBy:
Enabled: false
# Same as above, #find_by is not available until Rails 4
Rails/FindBy:
Enabled: false
# This should be the programmer's discretion, perhaps we should review all of
# the uses of it an make specific exceptions though.
Rails/SkipsModelValidations:

File diff suppressed because it is too large Load Diff

View File

@@ -4,6 +4,8 @@ cache: bundler
bundler_args: --without development
rvm:
- "2.1.5"
addons:
postgresql: "9.5"
# Set the timezone for phantomjs with TZ
# Set the timezone for karma with TIMEZONE
@@ -22,9 +24,6 @@ env:
- CI_NODE_INDEX=3
- CI_NODE_INDEX=4 KARMA="true" GITHUB_DEPLOY="true"
before_install:
- ./script/upgrade_bundler.sh
before_script:
- cp config/database.travis.yml config/database.yml
- cp config/application.yml.example config/application.yml
@@ -43,7 +42,6 @@ before_script:
script:
- 'if [ "$KARMA" = "true" ]; then bundle exec rake karma:run; else echo "Skipping karma run"; fi'
#- "KNAPSACK_GENERATE_REPORT=true bundle exec rspec spec"
- "bundle exec rake 'knapsack:rspec[--tag ~performance]'"
after_success:

View File

@@ -1,36 +1,68 @@
See this here post on raising a github issue:
https://community.openfoodnetwork.org/t/how-to-raise-a-github-issue/912
# Contributing
We love pull requests from everyone. Any contribution is valuable, but there are two issue streams that we especially love people to work on:
We love pull requests from everyone. Here are some instructions for
contributing code to Open Food Network. See the [developer wiki](https://github.com/openfoodfoundation/openfoodnetwork/wiki) for more information.
1) Our delivery backlog, is managed via a ZenHub board (ZenHub extensions are available for most major browsers). We use a Kanban-style approach, whereby devs pick issues from the top of the backlog which has been organised according to current priorities. If you have some time and are interested in working on some issues from the backlog, please make yourself known on the [#dev](https://openfoodnetwork.slack.com/messages/C2GQ45KNU) channel on Slack and we can direct you to the most appropriate issue to pick up.
Fork, then clone the repo:
2) Our list of bugs and other self-contained issues that we consider to be a good starting point for new contributors, or devs who arent able to commit to seeing a whole feature through. These issues are marked with the `# good first issue` label.
git clone git@github.com:your-username/openfoodnetwork.git
## Set up
Follow the instructions in README.markdown to set up your machine.
Set up your local development environment by following the appropriate guide from the `Development environment setup` section in the [developer wiki](https://github.com/openfoodfoundation/openfoodnetwork/wiki).
Make sure the tests pass:
Add an `upstream` remote that points to the main repo:
rspec spec
cd ~/location-of-your-local-ofn-repo
git remote add upstream https://github.com/openfoodfoundation/openfoodnetwork
Make your change. Add tests for your change. Make the tests pass:
If you haven't already done so, fork this repo using the `Fork` button in the top-right corner of this screen. Then ensure that your fork is listed as the `origin` remote on your local machine.
rspec spec
git remote set-url origin https://github.com/your-username/openfoodnetwork
Push to your fork and [submit a pull request][pr].
Fetch the latest version of `master` from `upstream` (ie. the main repo):
[pr]: https://github.com/openfoodfoundation/openfoodnetwork/compare/
git fetch upstream master
At this point you're waiting on us. We may suggest some changes or
improvements or alternatives.
Create a new branch on your local machine for (based on `upstream/master`):
To increase the chance that your pull request is swiftly accepted:
git checkout -b branch-name-here --no-track upstream/master
If you want to run the whole test suite, we recommend using a free CI service to run your tests in parallel. Running the whole suite locally in series is likely to take > 40 minutes. [TravisCI][travis] and [SemaphoreCI][semaphore] both work great in our experience. Either way, make sure the tests pass on your new branch:
bundle exec rspec spec
## Making a change
Make your changes to the codebase. We recommend using TDD. Add a test, make changes and get the test suite back to green.
bundle exec rspec spec
Once the tests are passing you can commit your changes. See [Making a great commit][great-commit] for more tips.
git add .
git commit -m "Add a concise commit message describing your change here"
Push your changes to a branch on your fork:
git push origin branch-name-here
## 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]].
TL;DR:
* Write tests
* Make sure the whole test suite is passing
* Keep your PR small, with a single focus
* Maintain a clean commit history
* Use a style consistent with the rest of the codebase
* Before submitting, [rebase your work][rebase] on the current master branch
From here, your pull request will progress through the [Review, Test, Merge & Deploy process][process].
[pr]: https://github.com/openfoodfoundation/openfoodnetwork/compare/
[great-pr]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Making-a-great-pull-request
[great-commit]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Making-a-great-commit
[process]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/The-process-of-review%2C-test%2C-merge-and-deploy
[rebase]: https://www.atlassian.com/git/tutorials/merging-vs-rebasing/workflow-walkthrough
[travis]: https://travis-ci.org/
[semaphore]: https://semaphoreci.com/

38
Gemfile
View File

@@ -1,5 +1,6 @@
source 'https://rubygems.org'
ruby "2.1.5"
git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
gem 'rails', '3.2.21'
gem 'rails-i18n', '~> 3.0.0'
@@ -10,15 +11,15 @@ gem 'i18n-js', '~> 3.0.0'
gem 'nokogiri', '>= 1.6.7.1'
gem 'pg'
gem 'spree', github: 'openfoodfoundation/spree', branch: 'step-6a', ref: '5a76d45'
gem 'spree', github: 'openfoodfoundation/spree', branch: 'step-6a', ref: '86bf87f1b1e1b299edc8cd10a2486e44ba0a3987'
gem 'spree_i18n', github: 'spree/spree_i18n', branch: '1-3-stable'
gem 'spree_auth_devise', github: 'openfoodfoundation/spree_auth_devise', branch: 'spree-upgrade-intermediate'
# Our branch contains two changes
# - Pass customer email and phone number to PayPal (merged to upstream master)
# - Change type of password from string to password to hide it in the form
gem 'spree_paypal_express', :github => "openfoodfoundation/better_spree_paypal_express", :branch => "spree-upgrade-intermediate"
#gem 'spree_paypal_express', :github => "spree-contrib/better_spree_paypal_express", :branch => "1-3-stable"
gem 'spree_paypal_express', github: "openfoodfoundation/better_spree_paypal_express", branch: "spree-upgrade-intermediate"
#gem 'spree_paypal_express', github: "spree-contrib/better_spree_paypal_express", branch: "1-3-stable"
gem 'stripe', '~> 3.3.1'
gem 'activemerchant', '~> 1.71.0'
@@ -30,7 +31,7 @@ gem 'daemons'
# Fix bug in simple_form preventing collection_check_boxes usage within form_for block
# When merged, revert to upstream gem
gem 'simple_form', :github => 'RohanM/simple_form'
gem 'simple_form', github: 'RohanM/simple_form'
gem 'unicorn'
gem 'angularjs-rails', '1.5.5'
@@ -48,14 +49,14 @@ gem 'representative_view'
gem 'rabl'
gem "active_model_serializers"
gem 'oj'
gem 'deface', :github => 'spree/deface', :ref => '1110a13'
gem 'deface', github: 'spree/deface', ref: '1110a13'
gem 'paperclip'
gem 'dalli'
gem 'geocoder'
gem 'gmaps4rails'
gem 'spinjs-rails'
gem 'rack-ssl', :require => 'rack/ssl'
gem 'custom_error_message', :github => 'jeremydurham/custom-err-msg'
gem 'rack-ssl', require: 'rack/ssl'
gem 'custom_error_message', github: 'jeremydurham/custom-err-msg'
gem 'angularjs-file-upload-rails', '~> 1.1.6'
gem 'roadie-rails', '~> 1.0.3'
gem 'figaro'
@@ -63,6 +64,7 @@ gem 'blockenspiel'
gem 'acts-as-taggable-on', '~> 3.4'
gem 'paper_trail', '~> 3.0.8'
gem 'diffy'
gem 'skylight', '< 2.0'
gem 'wicked_pdf'
gem 'wkhtmltopdf-binary'
@@ -97,23 +99,22 @@ gem 'jquery-rails'
gem 'jquery-migrate-rails'
gem 'css_splitter'
gem 'ofn-qz', github: 'openfoodfoundation/ofn-qz'
gem 'ofn-qz', github: 'openfoodfoundation/ofn-qz', ref: '60da2ae4c44cbb4c8d602f59fb5fff8d0f21db3c'
group :test, :development do
# Pretty printed test output
gem 'turn', '~> 0.8.3', :require => false
gem 'fuubar'
gem 'rspec-rails'
gem 'fuubar', '~> 2.2.0'
gem 'rspec-rails', ">= 3.5.2"
gem 'shoulda-matchers'
gem 'factory_girl_rails', :require => false
gem 'capybara'
gem 'database_cleaner', '0.7.1', :require => false
gem 'factory_girl_rails', require: false
gem 'capybara', '>= 2.15.4'
gem 'database_cleaner', '0.7.1', require: false
gem 'awesome_print'
gem 'letter_opener'
gem 'letter_opener', '>= 1.4.1'
gem 'timecop'
gem 'poltergeist'
gem 'poltergeist', '>= 1.16.0'
gem 'rspec-retry'
gem 'json_spec'
gem 'json_spec', '~> 1.1.4'
gem 'unicorn-rails'
gem 'atomic'
gem 'knapsack'
@@ -130,10 +131,11 @@ group :development do
gem 'pry-byebug', '>= 3.4.3'
gem 'debugger-linecache'
gem 'guard'
gem 'listen', '3.0.8' # 3.1.0 requires ruby 2.2
gem 'guard-livereload'
gem 'rack-livereload'
gem 'guard-rails'
gem 'guard-rspec'
gem 'guard-rspec', '~> 4.7.3'
gem 'parallel_tests'
gem 'rubocop', '>= 0.49.1'

View File

@@ -1,5 +1,5 @@
GIT
remote: git://github.com/RohanM/simple_form.git
remote: https://github.com/RohanM/simple_form.git
revision: 45f08a213b40f3d4bda5f5398db841137587160a
specs:
simple_form (2.0.2)
@@ -7,13 +7,13 @@ GIT
activemodel (~> 3.0)
GIT
remote: git://github.com/jeremydurham/custom-err-msg.git
remote: https://github.com/jeremydurham/custom-err-msg.git
revision: 3a8ec9dddc7a5b0aab7c69a6060596de300c68f4
specs:
custom_error_message (1.1.1)
GIT
remote: git://github.com/openfoodfoundation/better_spree_paypal_express.git
remote: https://github.com/openfoodfoundation/better_spree_paypal_express.git
revision: 8d95f4544c682634812becaf50999fba0cd04df0
branch: spree-upgrade-intermediate
specs:
@@ -22,16 +22,17 @@ GIT
spree_core (~> 1.3.99)
GIT
remote: git://github.com/openfoodfoundation/ofn-qz.git
revision: 024680ccea429b2e5428d7b964fa67c52add34ec
remote: https://github.com/openfoodfoundation/ofn-qz.git
revision: 60da2ae4c44cbb4c8d602f59fb5fff8d0f21db3c
ref: 60da2ae4c44cbb4c8d602f59fb5fff8d0f21db3c
specs:
ofn-qz (0.1.0)
railties (~> 3.1)
GIT
remote: git://github.com/openfoodfoundation/spree.git
revision: 5a76d456ff70aea7aae3d25156558d71eb7febf2
ref: 5a76d45
remote: https://github.com/openfoodfoundation/spree.git
revision: 86bf87f1b1e1b299edc8cd10a2486e44ba0a3987
ref: 86bf87f1b1e1b299edc8cd10a2486e44ba0a3987
branch: step-6a
specs:
spree (1.3.99)
@@ -91,7 +92,7 @@ GIT
spree_core (= 1.3.99)
GIT
remote: git://github.com/openfoodfoundation/spree_auth_devise.git
remote: https://github.com/openfoodfoundation/spree_auth_devise.git
revision: da9eecefc6fe13dedf4c6f3febec79caad839ec3
branch: spree-upgrade-intermediate
specs:
@@ -103,7 +104,7 @@ GIT
spree_frontend (~> 1.3.6)
GIT
remote: git://github.com/spree/deface.git
remote: https://github.com/spree/deface.git
revision: 1110a1336252109bce7f98f9182042e0bc2930ae
ref: 1110a13
specs:
@@ -113,7 +114,7 @@ GIT
rails (>= 3.1)
GIT
remote: git://github.com/spree/spree_i18n.git
remote: https://github.com/spree/spree_i18n.git
revision: 752eb67204e9c5a4e22b62591a8fd55fe2285e43
branch: 1-3-stable
specs:
@@ -123,7 +124,7 @@ GIT
spree_core (>= 1.1)
GIT
remote: git://github.com/willrjmarshall/foundation_rails_helper.git
remote: https://github.com/willrjmarshall/foundation_rails_helper.git
revision: 4d5d53fdc4b1fb71e66524d298c5c635de82cfbb
branch: rails3
specs:
@@ -173,7 +174,8 @@ GEM
acts-as-taggable-on (3.5.0)
activerecord (>= 3.2, < 5)
acts_as_list (0.1.9)
addressable (2.4.0)
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
andand (1.3.3)
angular-rails-templates (0.2.0)
railties (>= 3.1)
@@ -181,7 +183,6 @@ GEM
tilt
angularjs-file-upload-rails (1.1.6)
angularjs-rails (1.5.5)
ansi (1.4.2)
arel (3.0.3)
ast (2.3.0)
atomic (1.1.99)
@@ -200,15 +201,13 @@ GEM
builder (3.0.4)
byebug (9.0.6)
cancan (1.6.8)
capybara (2.7.1)
capybara (2.18.0)
addressable
mime-types (>= 1.16)
mini_mime (>= 0.1.3)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (~> 2.0)
celluloid (0.15.2)
timers (~> 1.1.0)
xpath (>= 2.0, < 4.0)
chronic (0.10.2)
chunky_png (1.3.4)
climate_control (0.1.0)
@@ -266,24 +265,24 @@ GEM
warden (~> 1.2.1)
devise-encryptable (0.1.2)
devise (>= 2.1.0)
diff-lcs (1.2.4)
diff-lcs (1.3)
diffy (3.1.0)
em-websocket (0.5.0)
em-websocket (0.5.1)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.5.3)
http_parser.rb (~> 0.6.0)
erubis (2.7.0)
eventmachine (1.2.3)
excon (0.45.4)
execjs (2.6.0)
factory_girl (3.3.0)
factory_girl (4.9.0)
activesupport (>= 3.0.0)
factory_girl_rails (3.3.0)
factory_girl (~> 3.3.0)
factory_girl_rails (4.9.0)
factory_girl (~> 4.9.0)
railties (>= 3.0.0)
faraday (0.9.2)
multipart-post (>= 1.2, < 3)
ffaker (1.15.0)
ffi (1.9.3)
ffi (1.9.18)
figaro (0.7.0)
bundler (~> 1.0)
rails (>= 3, < 5)
@@ -404,31 +403,38 @@ GEM
foundation-rails (5.5.0.0)
railties (>= 3.1.0)
sass (>= 3.2.0, < 3.4)
fuubar (1.3.3)
rspec (>= 2.14.0, < 3.1.0)
fuubar (2.2.0)
rspec-core (~> 3.0)
ruby-progressbar (~> 1.4)
geocoder (1.1.8)
gmaps4rails (1.5.6)
guard (2.2.4)
guard (2.14.1)
formatador (>= 0.2.4)
listen (~> 2.1)
listen (>= 2.7, < 4.0)
lumberjack (~> 1.0)
nenv (~> 0.1)
notiffany (~> 0.0)
pry (>= 0.9.12)
shellany (~> 0.0)
thor (>= 0.18.1)
guard-livereload (2.0.1)
guard-compat (1.2.1)
guard-livereload (2.5.2)
em-websocket (~> 0.5)
guard (~> 2.0)
guard (~> 2.8)
guard-compat (~> 1.0)
multi_json (~> 1.8)
guard-rails (0.4.7)
guard (>= 0.2.2)
guard-rspec (4.0.4)
guard (>= 2.1.1)
rspec (~> 2.14)
guard-rails (0.7.2)
guard (~> 2.11)
guard-compat (~> 1.0)
guard-rspec (4.7.3)
guard (~> 2.1)
guard-compat (~> 1.1)
rspec (>= 2.99.0, < 4.0)
haml (4.0.4)
tilt
highline (1.6.15)
hike (1.2.3)
http_parser.rb (0.5.3)
http_parser.rb (0.6.0)
httparty (0.9.0)
multi_json (~> 1.0)
multi_xml
@@ -446,33 +452,32 @@ GEM
railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0)
json (1.8.6)
json_spec (1.1.1)
json_spec (1.1.5)
multi_json (~> 1.0)
rspec (~> 2.0)
rspec (>= 2.0, < 4.0)
jwt (1.5.4)
kaminari (0.13.0)
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
railties (>= 3.0.0)
kgio (2.9.3)
knapsack (1.5.1)
knapsack (1.16.0)
rake
timecop (>= 0.1.0)
launchy (2.1.2)
launchy (2.4.3)
addressable (~> 2.3)
letter_opener (1.0.0)
launchy (>= 2.0.4)
letter_opener (1.6.0)
launchy (~> 2.2)
libv8 (3.16.14.11)
listen (2.2.0)
celluloid (>= 0.15.2)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
lumberjack (1.0.4)
listen (3.0.8)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
lumberjack (1.0.12)
mail (2.5.4)
mime-types (~> 1.16)
treetop (~> 1.4.8)
method_source (0.9.0)
mime-types (1.25.1)
mini_mime (0.1.4)
mini_portile2 (2.1.0)
momentjs-rails (2.5.1)
railties (>= 3.1)
@@ -481,9 +486,13 @@ GEM
multi_json (1.12.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
nenv (0.3.0)
newrelic_rpm (3.12.0.288)
nokogiri (1.6.8.1)
mini_portile2 (~> 2.1.0)
notiffany (0.1.1)
nenv (~> 0.1)
shellany (~> 0.0)
oauth2 (1.2.0)
faraday (>= 0.8, < 0.10)
jwt (~> 1.0)
@@ -511,28 +520,28 @@ GEM
paypal-sdk-merchant (1.106.1)
paypal-sdk-core (~> 0.2.3)
pg (0.13.2)
poltergeist (1.9.0)
poltergeist (1.16.0)
capybara (~> 2.1)
cliver (~> 0.3.1)
multi_json (~> 1.0)
websocket-driver (>= 0.2.0)
polyamorous (0.5.0)
activerecord (~> 3.0)
polyglot (0.3.5)
powerpack (0.1.1)
pry (0.11.1)
pry (0.11.2)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
pry-byebug (3.4.3)
byebug (>= 9.0, < 9.1)
pry (~> 0.10)
public_suffix (3.0.0)
rabl (0.7.2)
activesupport (>= 2.3.14)
multi_json (~> 1.0)
rack (1.4.7)
rack-cache (1.7.0)
rack (>= 0.4)
rack-livereload (0.3.15)
rack-livereload (0.3.16)
rack
rack-ssl (1.3.4)
rack
@@ -564,9 +573,9 @@ GEM
actionpack (~> 3.0)
activerecord (~> 3.0)
polyamorous (~> 0.5.0)
rb-fsevent (0.9.3)
rb-inotify (0.9.2)
ffi (>= 0.5.0)
rb-fsevent (0.10.2)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
rdoc (3.12.2)
json (~> 1.4)
redcarpet (3.2.3)
@@ -588,24 +597,29 @@ GEM
roo (2.7.1)
nokogiri (~> 1)
rubyzip (~> 1.1, < 2.0.0)
rspec (2.14.1)
rspec-core (~> 2.14.0)
rspec-expectations (~> 2.14.0)
rspec-mocks (~> 2.14.0)
rspec-core (2.14.4)
rspec-expectations (2.14.0)
diff-lcs (>= 1.1.3, < 2.0)
rspec-mocks (2.14.2)
rspec-rails (2.14.2)
rspec (3.7.0)
rspec-core (~> 3.7.0)
rspec-expectations (~> 3.7.0)
rspec-mocks (~> 3.7.0)
rspec-core (3.7.0)
rspec-support (~> 3.7.0)
rspec-expectations (3.7.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.7.0)
rspec-mocks (3.7.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.7.0)
rspec-rails (3.7.2)
actionpack (>= 3.0)
activemodel (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 2.14.0)
rspec-expectations (~> 2.14.0)
rspec-mocks (~> 2.14.0)
rspec-retry (0.4.2)
rspec-core
rspec-core (~> 3.7.0)
rspec-expectations (~> 3.7.0)
rspec-mocks (~> 3.7.0)
rspec-support (~> 3.7.0)
rspec-retry (0.5.6)
rspec-core (> 3.3, < 3.8)
rspec-support (3.7.0)
rubocop (0.49.1)
parallel (~> 1.10)
parser (>= 2.3.3.1, < 3.0)
@@ -623,7 +637,10 @@ GEM
tilt (~> 1.3)
select2-rails (3.5.10)
thor (~> 0.14)
shoulda-matchers (1.1.0)
shellany (0.0.1)
shoulda-matchers (2.8.0)
activesupport (>= 3.0.0)
skylight (1.5.0)
activesupport (>= 3.0.0)
spinjs-rails (1.3)
rails (>= 3.1)
@@ -639,10 +656,9 @@ GEM
therubyracer (0.12.0)
libv8 (~> 3.16.14.0)
ref
thor (0.19.4)
thor (0.20.0)
tilt (1.4.1)
timecop (0.8.1)
timers (1.1.0)
timecop (0.9.1)
treetop (1.4.15)
polyglot
polyglot (>= 0.3.1)
@@ -650,8 +666,6 @@ GEM
turbo-sprockets-rails3 (0.3.6)
railties (> 3.2.8, < 4.0.0)
sprockets (>= 2.0.0)
turn (0.8.3)
ansi
tzinfo (0.3.53)
uglifier (2.7.1)
execjs (>= 0.3.0)
@@ -669,12 +683,12 @@ GEM
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
warden (1.2.6)
warden (1.2.7)
rack (>= 1.0)
webmock (1.8.11)
addressable (>= 2.2.7)
crack (>= 0.1.7)
websocket-driver (0.6.3)
websocket-driver (0.7.0)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2)
whenever (0.9.2)
@@ -683,7 +697,7 @@ GEM
wicked_pdf (1.1.0)
wkhtmltopdf-binary (0.12.3.1)
xml-simple (1.1.5)
xpath (2.0.0)
xpath (2.1.0)
nokogiri (~> 1.3)
PLATFORMS
@@ -703,7 +717,7 @@ DEPENDENCIES
blockenspiel
bugsnag
byebug (~> 9.0.0)
capybara
capybara (>= 2.15.4)
coffee-rails (~> 3.2.1)
compass-rails
css_splitter
@@ -723,23 +737,24 @@ DEPENDENCIES
foundation-icons-sass-rails
foundation-rails
foundation_rails_helper!
fuubar
fuubar (~> 2.2.0)
geocoder
gmaps4rails
guard
guard-livereload
guard-rails
guard-rspec
guard-rspec (~> 4.7.3)
haml
i18n (~> 0.6.11)
i18n-js (~> 3.0.0)
immigrant
jquery-migrate-rails
jquery-rails
json_spec
json_spec (~> 1.1.4)
jwt (~> 1.5)
knapsack
letter_opener
letter_opener (>= 1.4.1)
listen (= 3.0.8)
momentjs-rails
newrelic_rpm
nokogiri (>= 1.6.7.1)
@@ -750,7 +765,7 @@ DEPENDENCIES
paperclip
parallel_tests
pg
poltergeist
poltergeist (>= 1.16.0)
pry-byebug (>= 3.4.3)
rabl
rack-livereload
@@ -761,13 +776,14 @@ DEPENDENCIES
representative_view
roadie-rails (~> 1.0.3)
roo (~> 2.7.0)
rspec-rails
rspec-rails (>= 3.5.2)
rspec-retry
rubocop (>= 0.49.1)
sass (~> 3.3)
sass-rails (~> 3.2.3)
shoulda-matchers
simple_form!
skylight (< 2.0)
spinjs-rails
spree!
spree_auth_devise!
@@ -778,7 +794,6 @@ DEPENDENCIES
timecop
truncate_html
turbo-sprockets-rails3
turn (~> 0.8.3)
uglifier (>= 1.0.3)
unicorn
unicorn-rails
@@ -791,4 +806,4 @@ RUBY VERSION
ruby 2.1.5p273
BUNDLED WITH
1.15.4
1.16.1

View File

@@ -45,41 +45,15 @@ You can download the source with the command:
### Get it running
For those new to Rails, the following tutorial will help get you up to speed with configuring a Rails environment: http://guides.rubyonrails.org/getting_started.html .
For those new to Rails, the following tutorial will help get you up to speed with configuring a [Rails environment](http://guides.rubyonrails.org/getting_started.html).
First, check your dependencies: Ensure that you have Ruby 2.1.5 installed:
When ready, run `script/setup`. If the script succeeds you're ready to start developing. If not, take a look at the output as it should be informative enough to help you troubleshoot.
ruby --version
If you run into any other issues getting your local environment up and running please consult [the wiki](https://github.com/openfoodfoundation/openfoodnetwork/wiki).
Install the project's gem dependencies:
If still you get stuck do not hesitate to open an issue reporting the full output of the script.
cd openfoodnetwork
./script/upgrade_bundler.sh
bundle install
Configure the site:
cp config/application.yml.example config/application.yml
edit config/application.yml
Create a PostgreSQL user:
* Login as your system postrgresql priviledged user: `sudo -i -u postgres` (this may vary on your OS). Now your prompt looks like: `[postgres@your_host ~]$`
* Create the `ofn` database superuser and give it the password `f00d`:
```
createuser -s -P ofn
```
Create the development and test databases, using the settings specified in `config/database.yml`, and populate them with a schema and seed data:
```
bundle exec rake db:setup
```
Load some default data for your environment:
```
bundle exec rake openfoodnetwork:dev:load_sample_data
```
At long last, your dreams of spinning up a development server can be realised:
Now, your dreams of spinning up a development server can be realised:
```
bundle exec rails server
```

View File

@@ -19,6 +19,7 @@
//= require admin/spree_paypal_express
//= require ../shared/ng-infinite-scroll.min.js
//= require ../shared/ng-tags-input.min.js
//= require moment
//= require angular-rails-templates
//= require_tree ../templates/admin
//= require ./admin_ofn
@@ -39,6 +40,7 @@
//= require ./resources/resources
//= require ./shipping_methods/shipping_methods
//= require ./side_menu/side_menu
//= require ./subscriptions/subscriptions
//= require ./tag_rules/tag_rules
//= require ./taxons/taxons
//= require ./utils/utils
@@ -49,6 +51,14 @@
//= require textAngular.min.js
//= require i18n/translations
//= require darkswarm/i18n.translate.js
//
//= require moment
//= require moment/en-gb.js
//= require moment/es.js
//= require moment/fr.js
//= require moment/it.js
//= require moment/nb.js
//= require moment/pt-br.js
//= require moment/sv.js
//= require_tree .

View File

@@ -32,7 +32,6 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
$scope.filteredProducts = []
$scope.currentFilters = []
$scope.limit = 15
$scope.productsWithUnsavedVariants = []
$scope.query = ""
$scope.DisplayProperties = DisplayProperties
@@ -114,7 +113,6 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
display_name: null
on_hand: null
price: null
$scope.productsWithUnsavedVariants.push product
DisplayProperties.setShowVariants product.id, true
@@ -196,7 +194,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
filters: $scope.currentFilters
).success((data) ->
DirtyProducts.clear()
BulkProducts.updateVariantLists(data.products, $scope.productsWithUnsavedVariants)
BulkProducts.updateVariantLists(data.products || [])
$timeout -> $scope.displaySuccess()
).error (data, status) ->
if status == 400 && data.errors? && data.errors.length > 0

View File

@@ -2,6 +2,7 @@ angular.module("admin.customers").directive 'editAddressDialog', ($compile, $tem
restrict: 'A'
scope: true
link: (scope, element, attr) ->
template = null
scope.errors = []
scope.$watch 'address.country_id', (newVal) ->
@@ -18,19 +19,19 @@ angular.module("admin.customers").directive 'editAddressDialog', ($compile, $tem
else
scope.errors.push(t('admin.customers.index.update_address_error'))
template = $compile($templateCache.get('admin/edit_address_dialog.html'))(scope)
template.dialog(DialogDefaults)
element.bind 'click', (e) ->
if e.target.id == 'bill-address-link'
scope.addressType = 'bill_address'
else
scope.addressType = 'ship_address'
scope.address = scope.customer[scope.addressType]
scope.states = scope.filter_states(scope.address?.country_id)
template = $compile($templateCache.get('admin/edit_address_dialog.html'))(scope)
template.dialog(DialogDefaults)
template.dialog('open')
scope.$apply()
scope.filter_states = (countryID) ->
$filter('filter')(scope.availableCountries, {id: countryID})[0].states
return [] unless countryID
$filter('filter')(scope.availableCountries, {id: parseInt(countryID)}, true)[0].states

View File

@@ -12,7 +12,10 @@ angular.module("admin.customers").directive 'newCustomerDialog', ($compile, $tem
scope.submitted = true
scope.errors = []
if scope.new_customer_form.$valid
Customers.add(scope.email).$promise.then (data) ->
params =
enterprise_id: CurrentShop.shop.id
email: scope.email
Customers.add(params).$promise.then (data) ->
if data.id
scope.email = ""
scope.submitted = false

View File

@@ -8,4 +8,4 @@ angular.module("ofn.admin").directive "datetimepicker", ->
onSelect: (dateText, inst) ->
scope.$apply (scope) ->
# Fires ngModel.$parsers
ngModel.$setViewValue dateText
ngModel.$setViewValue dateText

View File

@@ -1 +1 @@
angular.module("admin.dropdown", ['templates'])
angular.module("admin.dropdown", ['admin.utils'])

View File

@@ -0,0 +1 @@
angular.module("admin.enterpriseRoles", [])

View File

@@ -4,10 +4,8 @@ angular.module("admin.enterprises")
$scope.PaymentMethods = EnterprisePaymentMethods.paymentMethods
$scope.ShippingMethods = EnterpriseShippingMethods.shippingMethods
$scope.navClear = NavigationCheck.clear
$scope.pristineEmail = $scope.Enterprise.email
$scope.menu = SideMenu
$scope.newManager = { id: '', email: (t('add_manager')) }
$scope.StatusMessage = StatusMessage
$scope.$watch 'enterprise_form.$dirty', (newValue) ->
@@ -36,6 +34,8 @@ angular.module("admin.enterprises")
$scope.removeManager = (manager) ->
if manager.id?
if manager.id == $scope.Enterprise.owner.id or manager.id == parseInt($scope.receivesNotifications)
return
for i, user of $scope.Enterprise.users when user.id == manager.id
$scope.Enterprise.users.splice i, 1
if $scope.enterprise_form?
@@ -46,6 +46,7 @@ angular.module("admin.enterprises")
manager =
id: manager.id
email: manager.email
confirmed: manager.confirmed
if (user for user in $scope.Enterprise.users when user.id == manager.id).length == 0
$scope.Enterprise.users.push manager
else

View File

@@ -0,0 +1,11 @@
angular.module('admin.enterprises').directive 'enterpriseLimit', (InfoDialog) ->
restrict: 'A'
scope: {
limit_reached: '=enterpriseLimit',
modal_message: '@modalMessage'
}
link: (scope, element, attr) ->
element.bind 'click', (event)->
if scope.limit_reached
event.preventDefault()
InfoDialog.open 'error', scope.modal_message

View File

@@ -1,7 +1,7 @@
angular.module("admin.enterprises")
.factory "EnterprisePaymentMethods", (enterprise, PaymentMethods) ->
new class EnterprisePaymentMethods
paymentMethods: PaymentMethods.paymentMethods
paymentMethods: PaymentMethods.all
constructor: ->
for payment_method in @paymentMethods

View File

@@ -1,7 +1,7 @@
angular.module("admin.enterprises")
.factory "EnterpriseShippingMethods", (enterprise, ShippingMethods) ->
new class EnterpriseShippingMethods
shippingMethods: ShippingMethods.shippingMethods
shippingMethods: ShippingMethods.all
constructor: ->
for shipping_method in @shippingMethods

View File

@@ -1,9 +0,0 @@
angular.module("admin.indexUtils").directive "datepicker", ->
require: "ngModel"
link: (scope, element, attrs, ngModel) ->
element.datepicker
dateFormat: "yy-mm-dd"
onSelect: (dateText, inst) ->
scope.$apply (scope) ->
# Fires ngModel.$parsers
ngModel.$setViewValue dateText

View File

@@ -1 +1,2 @@
angular.module("admin.indexUtils", ['admin.resources', 'ngSanitize', 'templates', 'admin.utils']).config ($httpProvider) ->
angular.module("admin.indexUtils", ['admin.resources', 'ngSanitize', 'templates', 'admin.utils']).config ($httpProvider) ->
$httpProvider.defaults.headers.common["X-CSRF-Token"] = $("meta[name=csrf-token]").attr("content");

View File

@@ -1,14 +1,16 @@
angular.module("admin.indexUtils").factory 'Panels', ->
new class Panels
panels: []
all: []
register: (ctrl, object, selected=null) ->
if ctrl? && object?
@panels.push { ctrl: ctrl, object: object, selected: selected }
existing = @panelFor(object)
newPanel = { ctrl: ctrl, object: object, selected: selected }
if existing then angular.extend(existing, newPanel) else @all.push(newPanel)
ctrl.select(selected) if selected?
toggle: (object, name, state=null) ->
panel = @findPanelByObject(object)
panel = @panelFor(object)
if panel.selected == name
@select(panel, null) unless state == "open"
else
@@ -18,5 +20,5 @@ angular.module("admin.indexUtils").factory 'Panels', ->
panel.selected = name
panel.ctrl.select(name)
findPanelByObject: (object) ->
(panel for panel in @panels when panel.object == object)[0]
panelFor: (object) ->
(@all.filter (panel) -> panel.object == object)[0]

View File

@@ -6,7 +6,7 @@ angular.module("admin.indexUtils").factory "pendingChanges", ($q, resources, Sta
add: (id, attr, change) =>
@pendingChanges["#{id}"] = {} unless @pendingChanges.hasOwnProperty("#{id}")
@pendingChanges["#{id}"]["#{attr}"] = change
StatusMessage.display('notice', "You have made #{@changeCount(@pendingChanges)} unsaved changes")
StatusMessage.display('notice', t('admin.unsaved_changes'))
removeAll: =>
@pendingChanges = {}

View File

@@ -3,8 +3,8 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
$scope.RequestMonitor = RequestMonitor
$scope.filteredLineItems = []
$scope.confirmDelete = true
$scope.startDate = formatDate daysFromToday -7
$scope.endDate = formatDate daysFromToday 1
$scope.startDate = moment().startOf('day').subtract(7, 'days').format('YYYY-MM-DD')
$scope.endDate = moment().startOf('day').format('YYYY-MM-DD')
$scope.bulkActions = [ { name: t("admin.orders.bulk_management.actions_delete"), callback: 'deleteLineItems' } ]
$scope.selectedUnitsProduct = {}
$scope.selectedUnitsVariant = {}
@@ -22,16 +22,16 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
$scope.refreshData = ->
unless !$scope.orderCycleFilter? || $scope.orderCycleFilter == 0
$scope.startDate = OrderCycles.byID[$scope.orderCycleFilter].first_order
$scope.endDate = OrderCycles.byID[$scope.orderCycleFilter].last_order
$scope.startDate = moment(OrderCycles.byID[$scope.orderCycleFilter].orders_open_at).format('YYYY-MM-DD')
$scope.endDate = moment(OrderCycles.byID[$scope.orderCycleFilter].orders_close_at).startOf('day').format('YYYY-MM-DD')
RequestMonitor.load $scope.orders = Orders.index("q[state_not_eq]": "canceled", "q[completed_at_not_null]": "true", "q[completed_at_gt]": "#{parseDate($scope.startDate)}", "q[completed_at_lt]": "#{parseDate($scope.endDate)}")
RequestMonitor.load $scope.lineItems = LineItems.index("q[order][state_not_eq]": "canceled", "q[order][completed_at_not_null]": "true", "q[order][completed_at_gt]": "#{parseDate($scope.startDate)}", "q[order][completed_at_lt]": "#{parseDate($scope.endDate)}")
RequestMonitor.load $scope.orders = Orders.index("q[state_not_eq]": "canceled", "q[completed_at_not_null]": "true", "q[completed_at_gteq]": "#{moment($scope.startDate).format()}", "q[completed_at_lt]": "#{moment($scope.endDate).add(1,'day').format()}")
RequestMonitor.load $scope.lineItems = LineItems.index("q[order][state_not_eq]": "canceled", "q[order][completed_at_not_null]": "true", "q[order][completed_at_gteq]": "#{moment($scope.startDate).format()}", "q[order][completed_at_lt]": "#{moment($scope.endDate).add(1,'day').format()}")
unless $scope.initialized
RequestMonitor.load $scope.distributors = Enterprises.index(action: "for_line_items", ams_prefix: "basic", "q[sells_in][]": ["own", "any"])
RequestMonitor.load $scope.orderCycles = OrderCycles.index(ams_prefix: "basic", as: "distributor", "q[orders_close_at_gt]": "#{daysFromToday(-90)}")
RequestMonitor.load $scope.suppliers = Enterprises.index(action: "for_line_items", ams_prefix: "basic", "q[is_primary_producer_eq]": "true")
RequestMonitor.load $scope.distributors = Enterprises.index(action: "visible", ams_prefix: "basic", "q[sells_in][]": ["own", "any"])
RequestMonitor.load $scope.orderCycles = OrderCycles.index(ams_prefix: "basic", as: "distributor", "q[orders_close_at_gt]": "#{moment().subtract(90,'days').format()}")
RequestMonitor.load $scope.suppliers = Enterprises.index(action: "visible", ams_prefix: "basic", "q[is_primary_producer_eq]": "true")
RequestMonitor.load $q.all([$scope.orders.$promise, $scope.distributors.$promise, $scope.orderCycles.$promise]).then ->
Dereferencer.dereferenceAttr $scope.orders, "distributor", Enterprises.byID
@@ -142,31 +142,3 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
if lineItem.quantity > 0
lineItem.final_weight_volume = LineItems.pristineByID[lineItem.id].final_weight_volume * lineItem.quantity / LineItems.pristineByID[lineItem.id].quantity
$scope.weightAdjustedPrice(lineItem)
daysFromToday = (days) ->
now = new Date
now.setHours(0)
now.setMinutes(0)
now.setSeconds(0)
now.setDate( now.getDate() + days )
now
formatDate = (date) ->
year = date.getFullYear()
month = twoDigitNumber date.getMonth() + 1
day = twoDigitNumber date.getDate()
return year + "-" + month + "-" + day
formatTime = (date) ->
hours = twoDigitNumber date.getHours()
mins = twoDigitNumber date.getMinutes()
secs = twoDigitNumber date.getSeconds()
return hours + ":" + mins + ":" + secs
parseDate = (dateString) ->
new Date(Date.parse(dateString))
twoDigitNumber = (number) ->
twoDigits = "" + number
twoDigits = ("0" + number) if number < 10
twoDigits

View File

@@ -1,10 +1,11 @@
angular.module('admin.orderCycles')
.controller 'AdminCreateOrderCycleCtrl', ($scope, $filter, $window, OrderCycle, Enterprise, EnterpriseFee, ocInstance, StatusMessage) ->
.controller 'AdminCreateOrderCycleCtrl', ($scope, $filter, $window, OrderCycle, Enterprise, EnterpriseFee, Schedules, RequestMonitor, ocInstance, StatusMessage) ->
$scope.enterprises = Enterprise.index(coordinator_id: ocInstance.coordinator_id)
$scope.supplier_enterprises = Enterprise.producer_enterprises
$scope.distributor_enterprises = Enterprise.hub_enterprises
$scope.supplied_products = Enterprise.supplied_products
$scope.enterprise_fees = EnterpriseFee.index(coordinator_id: ocInstance.coordinator_id)
$scope.schedules = Schedules.index()
$scope.OrderCycle = OrderCycle
$scope.order_cycle = OrderCycle.new({ coordinator_id: ocInstance.coordinator_id})
@@ -18,7 +19,7 @@ angular.module('admin.orderCycles')
StatusMessage.setValidation(isValid)
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded && !RequestMonitor.loading
$scope.suppliedVariants = (enterprise_id) ->
Enterprise.suppliedVariants(enterprise_id)
@@ -89,4 +90,3 @@ angular.module('admin.orderCycles')
$scope.cancel = (destination) ->
$window.location = destination

View File

@@ -1,11 +1,12 @@
angular.module('admin.orderCycles')
.controller 'AdminEditOrderCycleCtrl', ($scope, $filter, $location, $window, OrderCycle, Enterprise, EnterpriseFee, StatusMessage) ->
.controller 'AdminEditOrderCycleCtrl', ($scope, $filter, $location, $window, OrderCycle, Enterprise, EnterpriseFee, StatusMessage, Schedules, RequestMonitor) ->
order_cycle_id = $location.absUrl().match(/\/admin\/order_cycles\/(\d+)/)[1]
$scope.enterprises = Enterprise.index(order_cycle_id: order_cycle_id)
$scope.supplier_enterprises = Enterprise.producer_enterprises
$scope.distributor_enterprises = Enterprise.hub_enterprises
$scope.supplied_products = Enterprise.supplied_products
$scope.enterprise_fees = EnterpriseFee.index(order_cycle_id: order_cycle_id)
$scope.schedules = Schedules.index()
$scope.OrderCycle = OrderCycle
$scope.order_cycle = OrderCycle.load(order_cycle_id)
@@ -19,7 +20,7 @@ angular.module('admin.orderCycles')
StatusMessage.setValidation(isValid)
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded && !RequestMonitor.loading
$scope.suppliedVariants = (enterprise_id) ->
Enterprise.suppliedVariants(enterprise_id)

View File

@@ -0,0 +1,45 @@
angular.module("admin.orderCycles").controller "OrderCyclesCtrl", ($scope, $q, Columns, StatusMessage, RequestMonitor, OrderCycles, Enterprises, Schedules, Dereferencer) ->
$scope.RequestMonitor = RequestMonitor
$scope.columns = Columns.columns
$scope.saveAll = -> OrderCycles.saveChanges($scope.order_cycles_form)
$scope.ordersCloseAtLimit = -31 # days
$scope.involvingFilter = 0
$scope.scheduleFilter = 0
compileData = ->
for schedule in $scope.schedules
Dereferencer.dereference(schedule.order_cycles, OrderCycles.byID)
for orderCycle in $scope.orderCycles
coordinator = Enterprises.byID[orderCycle.coordinator.id]
orderCycle.coordinator = coordinator if coordinator?
Dereferencer.dereference(orderCycle.producers, Enterprises.byID)
Dereferencer.dereference(orderCycle.shops, Enterprises.byID)
Dereferencer.dereference(orderCycle.schedules, Schedules.byID)
orderCycle.involvedEnterpriseIDs = [orderCycle.coordinator.id]
orderCycle.producerNames = orderCycle.producers.map((producer) -> orderCycle.involvedEnterpriseIDs.push(producer.id); producer.name).join(", ")
orderCycle.shopNames = orderCycle.shops.map((shop) -> orderCycle.involvedEnterpriseIDs.push(shop.id); shop.name).join(", ")
# NOTE: this is using the Enterprises service from the admin.enterprises module
RequestMonitor.load ($scope.enterprises = Enterprises.index(action: "visible", ams_prefix: "basic")).$promise
$scope.schedules = Schedules.index()
$scope.orderCycles = OrderCycles.index(ams_prefix: "index", "q[orders_close_at_gt]": "#{daysFromToday($scope.ordersCloseAtLimit)}")
RequestMonitor.load $q.all([$scope.enterprises.$promise, $scope.schedules.$promise, $scope.orderCycles.$promise]).then -> compileData()
$scope.$watch 'order_cycles_form.$dirty', (newVal, oldVal) ->
StatusMessage.display 'notice', "You have unsaved changes" if newVal
$scope.showMore = (days) ->
$scope.ordersCloseAtLimit -= days
existingIDs = Object.keys(OrderCycles.byID)
orderCycles = OrderCycles.index(ams_prefix: "index", "q[orders_close_at_gt]": "#{daysFromToday($scope.ordersCloseAtLimit)}", "q[id_not_in][]": existingIDs)
orderCycles.$promise.then ->
$scope.orderCycles.push(orderCycle) for orderCycle in orderCycles
compileData()
daysFromToday = (days) ->
now = new Date
now.setHours(0)
now.setMinutes(0)
now.setSeconds(0)
now.setDate( now.getDate() + days )
now

View File

@@ -1,6 +1,7 @@
angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl", ($scope, $window, OrderCycle, Enterprise, EnterpriseFee, StatusMessage, ocInstance) ->
angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl", ($scope, $window, OrderCycle, Enterprise, EnterpriseFee, StatusMessage, Schedules, RequestMonitor, ocInstance) ->
$scope.StatusMessage = StatusMessage
$scope.OrderCycle = OrderCycle
$scope.schedules = Schedules.index()
$scope.order_cycle = OrderCycle.new {coordinator_id: ocInstance.coordinator_id}, =>
# TODO: make this a get method, which only fetches one enterprise
$scope.enterprises = Enterprise.index {coordinator_id: ocInstance.coordinator_id}, (enterprises) =>
@@ -26,7 +27,7 @@ angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl"
OrderCycle.order_cycle.coordinator_id = enterprise.id
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded && !RequestMonitor.loading
$scope.removeDistributionOfVariant = angular.noop

View File

@@ -1,10 +1,11 @@
angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl", ($scope, $location, $window, OrderCycle, Enterprise, EnterpriseFee, StatusMessage) ->
angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl", ($scope, $location, $window, OrderCycle, Enterprise, EnterpriseFee, Schedules, RequestMonitor, StatusMessage) ->
$scope.orderCycleId = ->
$location.absUrl().match(/\/admin\/order_cycles\/(\d+)/)[1]
$scope.StatusMessage = StatusMessage
$scope.enterprises = Enterprise.index(order_cycle_id: $scope.orderCycleId())
$scope.enterprise_fees = EnterpriseFee.index(order_cycle_id: $scope.orderCycleId())
$scope.schedules = Schedules.index()
$scope.OrderCycle = OrderCycle
$scope.order_cycle = OrderCycle.load $scope.orderCycleId(), (order_cycle) =>
$scope.init()
@@ -16,7 +17,7 @@ angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl",
StatusMessage.setValidation(isValid)
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded && !RequestMonitor.loading
$scope.init = ->
$scope.outgoing_exchange = OrderCycle.order_cycle.outgoing_exchanges[0]

View File

@@ -0,0 +1,26 @@
angular.module("admin.orderCycles").directive 'orderCyclesSelector', ($timeout, OrderCycles) ->
restrict: 'C'
templateUrl: 'admin/order_cycles_selector.html'
link: (scope, element, attr) ->
scope.orderCycles = OrderCycles.all.filter (oc) -> oc.viewing_as_coordinator
$timeout ->
scope.selections =
available: scope.availableOrderCycles[0]
selected: scope.selectedOrderCycles[0]
scope.add = (orderCycle) ->
orderCycle ?= scope.selections.available
index = scope.availableOrderCycles.indexOf(orderCycle)
if index > -1
scope.selectedOrderCycles.push orderCycle
scope.selections.available = scope.availableOrderCycles[index+1] || scope.availableOrderCycles[index-1]
scope.selections.selected = orderCycle
scope.remove = (orderCycle) ->
orderCycle ?= scope.selections.selected
index = scope.selectedOrderCycles.indexOf(orderCycle)
if index > -1
scope.selectedOrderCycles.splice(index, 1)
scope.selections.selected = scope.selectedOrderCycles[index] || scope.selectedOrderCycles[index-1]
scope.selections.available = orderCycle

View File

@@ -0,0 +1,56 @@
angular.module("admin.orderCycles").directive 'scheduleDialog', ($window, $compile, $injector, $templateCache, DialogDefaults, OrderCycles, Schedules) ->
restrict: 'A'
scope:
scheduleId: '@'
showMore: '&'
link: (scope, element, attr) ->
# Link opening of dialog to click event on element
element.bind 'click', (e) ->
existing = Schedules.byID[scope.scheduleId]
scope.schedule =
id: existing?.id
name: existing?.name || ''
order_cycle_ids: existing?.order_cycle_ids || []
scope.selectedOrderCycles = []
scope.selectedOrderCycles.push orderCycle for orderCycle in (existing?.order_cycles || [])
scope.submitted = false
scope.errors = []
# Compile modal template
scope.template = $compile($templateCache.get('admin/schedule_dialog.html'))(scope)
# Set Dialog options
settings = angular.copy(DialogDefaults)
scope.template.dialog(angular.extend(settings,{width: $window.innerWidth * 0.6}))
scope.template.dialog(close: -> scope.template.remove())
scope.template.dialog('open')
scope.close = ->
scope.template.dialog('close')
return
scope.delete = ->
if confirm(t('are_you_sure'))
Schedules.remove(scope.schedule).$promise.then (data) ->
scope.close()
scope.loadMore = ->
scope.showMore().then ->
scope.availableOrderCycles = (orderCycle for id, orderCycle of OrderCycles.byID when orderCycle.id not in scope.schedule.order_cycle_ids)
scope.submit = ->
scope.schedule_form.$setPristine()
scope.submitted = true
scope.errors = []
return scope.errors.push(t('admin.order_cycles.index.no_order_cycles_error')) unless scope.selectedOrderCycles.length > 0
scope.schedule.order_cycle_ids = scope.selectedOrderCycles.map (oc) -> oc.id
if scope.schedule_form.$valid
method = if scope.schedule.id? then Schedules.update else Schedules.add
method(scope.schedule).$promise.then (data) ->
if data.id
scope.submitted = false
scope.template.dialog('close')
, (response) ->
if response.data.errors
scope.errors.push(error) for error in response.data.errors
else
scope.errors.push("Sorry! Could not create '#{scope.name}'")
return

View File

@@ -0,0 +1,15 @@
angular.module("admin.orderCycles").directive 'scheduleList', (RequestMonitor, Schedules) ->
restrict: 'E'
scope:
orderCycle: '='
template: "<div><span ng-repeat='schedule in schedules'>{{ schedule.name + ($last ? '' : ', ')}}</span></div>"
link: (scope, element, attr) ->
scope.schedules = []
scope.$watchCollection 'orderCycle.schedule_ids', (newValue, oldValue) ->
return unless newValue? && RequestMonitor.loadId > 0 # Request for schedules needs to have been sent
scope.schedules = []
RequestMonitor.loadQueue.then ->
for id in scope.orderCycle.schedule_ids
schedule = Schedules.byID[id]
scope.schedules.push schedule if schedule?

View File

@@ -0,0 +1,7 @@
angular.module("admin.orderCycles").filter "available", ($filter) ->
return (orderCycles, selectedOrderCycles) ->
return orderCycles unless selectedOrderCycles?.length > 0
$filter('filter')(orderCycles, (orderCycle) ->
(selectedOrderCycles.indexOf(orderCycle) == -1) &&
(orderCycle.coordinator.id == selectedOrderCycles[0].coordinator.id)
)

View File

@@ -0,0 +1,6 @@
angular.module("admin.orderCycles").filter "involving", ($filter) ->
return (orderCycles, enterpriseID) ->
return orderCycles if enterpriseID == 0
$filter('filter')(orderCycles, (orderCycle) ->
enterpriseID in orderCycle.involvedEnterpriseIDs
)

View File

@@ -0,0 +1,6 @@
angular.module("admin.orderCycles").filter "schedule", ($filter) ->
return (orderCycles, scheduleID) ->
return orderCycles if scheduleID == 0
$filter('filter')(orderCycles, (orderCycle) ->
scheduleID in orderCycle.schedules.map (oc) -> oc.id
)

View File

@@ -1,32 +0,0 @@
angular.module('admin.orderCycles', ['admin.utils', 'admin.indexUtils', 'ngTagsInput'])
.config ($httpProvider) ->
$httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content')
.directive 'datetimepicker', ($parse) ->
(scope, element, attrs) ->
# 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:ss'
showOn: "button"
buttonImage: "<%= asset_path 'datepicker/cal.gif' %>"
buttonImageOnly: true
stepMinute: 15
onSelect: (dateText, inst) ->
scope.$apply ->
parsed = $parse(attrs.datetimepicker)
parsed.assign(scope, dateText)
.directive 'ofnOnChange', ->
(scope, element, attrs) ->
element.bind 'change', ->
scope.$apply(attrs.ofnOnChange)
.directive 'ofnSyncDistributions', ->
(scope, element, attrs) ->
element.bind 'change', ->
if !$(this).is(':checked')
scope.$apply ->
scope.removeDistributionOfVariant(attrs.ofnSyncDistributions)

View File

@@ -0,0 +1,37 @@
angular.module('admin.orderCycles', ['ngTagsInput', 'admin.indexUtils', 'admin.enterprises'])
.config ($httpProvider) ->
$httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content')
.directive 'datetimepicker', ($timeout, $parse) ->
require: "ngModel"
link: (scope, element, attrs, ngModel) ->
$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:ss'
showOn: "button"
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)
)
.directive 'ofnOnChange', ->
(scope, element, attrs) ->
element.bind 'change', ->
scope.$apply(attrs.ofnOnChange)
.directive 'ofnSyncDistributions', ->
(scope, element, attrs) ->
element.bind 'change', ->
if !$(this).is(':checked')
scope.$apply ->
scope.removeDistributionOfVariant(attrs.ofnSyncDistributions)

View File

@@ -1,5 +1,7 @@
angular.module("admin.orders").directive 'customerSearchOverride', ->
restrict: 'C'
scope:
distributorId: '@'
link: (scope, element, attr) ->
formatCustomerResult = (customer) ->
customerTemplate
@@ -9,13 +11,14 @@ angular.module("admin.orders").directive 'customerSearchOverride', ->
element.select2
placeholder: Spree.translations.choose_a_customer
minimumInputLength: 3
ajax:
url: '/admin/search/customers.json'
datatype: 'json'
data: (term, page) ->
{
q: term
distributor_id: $('#distributor_id').val() # modified
distributor_id: scope.distributorId # modified
}
results: (data, page) ->
{ results: data }

View File

@@ -5,4 +5,9 @@ angular.module("admin.resources").factory 'OrderCycleResource', ($resource) ->
isArray: true
'update':
method: 'PUT'
'bulkUpdate':
method: 'POST'
isArray: true
params:
action: 'bulk_update'
})

View File

@@ -0,0 +1,16 @@
angular.module("admin.resources").factory 'ScheduleResource', ($resource) ->
$resource('/admin/schedules/:id/:action.json', {}, {
'index':
method: 'GET'
isArray: true
'create':
method: 'POST'
'update':
method: 'PUT'
params:
id: '@id'
'destroy':
method: 'DELETE'
params:
id: '@id'
})

View File

@@ -1,13 +1,14 @@
angular.module("admin.resources").factory "Customers", ($q, InfoDialog, RequestMonitor, CustomerResource, CurrentShop) ->
angular.module("admin.resources").factory "Customers", ($q, $injector, InfoDialog, RequestMonitor, CustomerResource) ->
new class Customers
all: []
byID: {}
pristineByID: {}
add: (email) ->
params =
enterprise_id: CurrentShop.shop.id
email: email
constructor: ->
if $injector.has('customers')
@load($injector.get('customers'))
add: (params) ->
CustomerResource.create params, (customer) =>
if customer.id
@all.unshift customer

View File

@@ -1,4 +1,4 @@
angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCycleResource) ->
angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCycleResource, RequestMonitor, StatusMessage) ->
new class OrderCycles
all: []
byID: {}
@@ -8,14 +8,13 @@ angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCy
if $injector.has('orderCycles')
@load($injector.get('orderCycles'))
index: (params={}, callback=null) ->
OrderCycleResource.index params, (data) =>
@load(data)
(callback || angular.noop)(data)
data
index: (params={}) ->
request = OrderCycleResource.index params, (data) => @load(data)
RequestMonitor.load(request.$promise)
request
load: (orderCycles) ->
for orderCycle in orderCycles
for orderCycle in orderCycles when orderCycle.id not in Object.keys(@byID)
@all.push orderCycle
@byID[orderCycle.id] = orderCycle
@pristineByID[orderCycle.id] = angular.copy(orderCycle)
@@ -30,14 +29,41 @@ angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCy
deferred.reject(response)
deferred.promise
saveChanges: (form) ->
changed = {}
for id, orderCycle of @byID when not @saved(orderCycle)
changed[Object.keys(changed).length] = @changesFor(orderCycle)
if Object.keys(changed).length > 0
StatusMessage.display('progress', "Saving...")
OrderCycleResource.bulkUpdate { order_cycle_set: { collection_attributes: changed } }, (data) =>
for orderCycle in data
delete orderCycle.coordinator
delete orderCycle.producers
delete orderCycle.distributors
angular.extend(@byID[orderCycle.id], orderCycle)
angular.extend(@pristineByID[orderCycle.id], orderCycle)
form.$setPristine() if form?
StatusMessage.display('success', "Order cycles have been updated.")
, (response) =>
StatusMessage.display('failure', "Oh no! I was unable to save your changes.")
saved: (order_cycle) ->
@diff(order_cycle).length == 0
diff: (order_cycle) ->
changed = []
for attr, value of order_cycle when not angular.equals(value, @pristineByID[order_cycle.id][attr])
changed.push attr unless attr is "$$hashKey"
changed.push attr if attr in @attrsToSave()
changed
changesFor: (orderCycle) ->
changes = { id: orderCycle.id }
for attr, value of orderCycle when not angular.equals(value, @pristineByID[orderCycle.id][attr])
changes[attr] = orderCycle[attr] if attr in @attrsToSave()
changes
attrsToSave: ->
['orders_open_at','orders_close_at']
resetAttribute: (order_cycle, attribute) ->
order_cycle[attribute] = @pristineByID[order_cycle.id][attribute]

View File

@@ -1,7 +1,7 @@
angular.module("admin.resources")
.factory "PaymentMethods", ($injector) ->
new class PaymentMethods
paymentMethods: []
all: []
byID: {}
pristineByID: {}
@@ -11,6 +11,6 @@ angular.module("admin.resources")
load: (paymentMethods) ->
for paymentMethod in paymentMethods
@paymentMethods.push paymentMethod
@all.push paymentMethod
@byID[paymentMethod.id] = paymentMethod
@pristineByID[paymentMethod.id] = angular.copy(paymentMethod)

View File

@@ -0,0 +1,52 @@
angular.module("admin.resources").factory "Schedules", ($q, $injector, RequestMonitor, ScheduleResource, OrderCycles, Dereferencer, StatusMessage) ->
new class Schedules
all: []
byID: {}
constructor: ->
if $injector.has('schedules')
@load($injector.get('schedules'))
load: (schedules) ->
for schedule in schedules
@all.push schedule
@byID[schedule.id] = schedule
add: (params) =>
ScheduleResource.create params, (schedule) =>
@byID[schedule.id] = schedule if schedule.id?
Dereferencer.dereference(schedule.order_cycles, OrderCycles.byID)
orderCycle.schedules.push(schedule) for orderCycle in schedule.order_cycles
StatusMessage.display 'success', "#{t('admin.order_cycles.index.created_schedule')}: '#{schedule.name}'"
update: (params) =>
ScheduleResource.update params, (schedule) =>
if schedule.id?
Dereferencer.dereference(schedule.order_cycles, OrderCycles.byID)
for orderCycle in @byID[schedule.id].order_cycles when orderCycle.id not in schedule.order_cycle_ids
if orderCycle.schedules # Only if we need to update the schedules
orderCycle.schedules.splice(i, 1) for s, i in orderCycle.schedules by -1 when s.id == schedule.id
for orderCycle in schedule.order_cycles when orderCycle.id not in @byID[schedule.id].order_cycle_ids
orderCycle.schedules.push(@byID[schedule.id])
angular.extend(@byID[schedule.id], schedule)
StatusMessage.display 'success', "#{t('admin.order_cycles.index.updated_schedule')}: '#{schedule.name}'"
remove: (schedule) ->
params = id: schedule.id
ScheduleResource.destroy params, =>
for orderCycle in @byID[schedule.id].order_cycles
if orderCycle.schedules # Only if we need to update the schedules
orderCycle.schedules.splice(i, 1) for s, i in orderCycle.schedules by -1 when s.id == schedule.id
delete @byID[schedule.id]
StatusMessage.display 'success', "#{t('admin.order_cycles.index.deleted_schedule')}: '#{schedule.name}'"
, (response) =>
errors = response.data.errors
if errors?
InfoDialog.open 'error', errors[0]
else
InfoDialog.open 'error', "Could not delete schedule: #{schedule.name}"
index: ->
request = ScheduleResource.index (data) => @load(data)
RequestMonitor.load(request.$promise)
request

View File

@@ -1,7 +1,7 @@
angular.module("admin.resources")
.factory "ShippingMethods", ($injector) ->
new class ShippingMethods
shippingMethods: []
all: []
byID: {}
pristineByID: {}
@@ -11,6 +11,6 @@ angular.module("admin.resources")
load: (shippingMethods) ->
for shippingMethod in shippingMethods
@shippingMethods.push shippingMethod
@all.push shippingMethod
@byID[shippingMethod.id] = shippingMethod
@pristineByID[shippingMethod.id] = angular.copy(shippingMethod)

View File

@@ -16,9 +16,9 @@ angular.module("ofn.admin").factory "BulkProducts", (PagedFetcher, dataFetcher,
@unpackProduct newProduct
@insertProductAfter(product, newProduct)
updateVariantLists: (serverProducts, productsWithUnsavedVariants) ->
for product in productsWithUnsavedVariants
server_product = @findProductInList(product.id, serverProducts)
updateVariantLists: (serverProducts) ->
for server_product in serverProducts
product = @findProductInList(server_product.id, @products)
product.variants = server_product.variants
@loadVariantUnitValues product

View File

@@ -0,0 +1,26 @@
angular.module("admin.subscriptions").controller "AddressController", ($scope, $filter, StatusMessage, availableCountries) ->
$scope.countries = availableCountries
$scope.statesFor = (country_id) ->
return [] unless country_id
$filter('filter')(availableCountries, {id: country_id})[0].states
$scope.billStates = $scope.statesFor($scope.subscription.bill_address.country_id)
$scope.shipStates = $scope.statesFor($scope.subscription.ship_address.country_id)
$scope.registerNextCallback 'address', ->
$scope.subscription_form.$submitted = true
if $scope.subscription_address_form.$valid
$scope.subscription_form.$setPristine()
StatusMessage.clear()
$scope.setView('products')
else
StatusMessage.display 'failure', t('admin.subscriptions.details.invalid_error')
$scope.registerBackCallback 'address', ->
StatusMessage.clear()
$scope.setView('details')
$scope.$watch 'subscription.bill_address.country_id', (newValue, oldValue) ->
$scope.billStates = $scope.statesFor(newValue) if newValue?
$scope.$watch 'subscription.ship_address.country_id', (newValue, oldValue) ->
$scope.shipStates = $scope.statesFor(newValue) if newValue?

View File

@@ -0,0 +1,38 @@
angular.module("admin.subscriptions").controller "DetailsController", ($scope, $http, CreditCardResource, StatusMessage) ->
$scope.cardRequired = false
$scope.registerNextCallback 'details', ->
$scope.subscription_form.$submitted = true
if $scope.subscription_details_form.$valid
$scope.subscription_form.$setPristine()
StatusMessage.clear()
$scope.setView('address')
else
StatusMessage.display 'failure', t('admin.subscriptions.details.invalid_error')
$scope.$watch "subscription.customer_id", (newValue, oldValue) ->
return if !newValue?
$scope.loadAddresses(newValue) unless $scope.subscription.id?
$scope.loadCreditCards(newValue)
$scope.$watch "subscription.payment_method_id", (newValue, oldValue) ->
return if !newValue?
paymentMethod = ($scope.paymentMethods.filter (pm) -> pm.id == newValue)[0]
return unless paymentMethod?
if paymentMethod.type == "Spree::Gateway::StripeConnect"
$scope.cardRequired = true
else
$scope.cardRequired = false
$scope.subscription.credit_card_id = null
$scope.loadAddresses = (customer_id) ->
$http.get("/admin/customers/#{customer_id}/addresses")
.success (response) =>
delete response.bill_address.id
delete response.ship_address.id
angular.extend($scope.subscription.bill_address, response.bill_address)
angular.extend($scope.subscription.ship_address, response.ship_address)
$scope.shipAddressFromBilling() unless response.ship_address.address1?
$scope.loadCreditCards = (customer_id) ->
$scope.creditCards = CreditCardResource.index(customer_id: customer_id)

View File

@@ -0,0 +1,10 @@
angular.module("admin.subscriptions").controller "OrderUpdateIssuesController", ($scope, OrderCycles) ->
$scope.proxyOrders = $scope.options.proxyOrders
$scope.orderCycleName = (id) ->
OrderCycles.byID[id].name
$scope.orderCycleCloses = (id) ->
closes_at = moment(OrderCycles.byID[id].orders_close_at)
text = if closes_at > moment() then t('js.closes') else t('js.closed')
"#{text} #{closes_at.fromNow()}"

View File

@@ -0,0 +1,22 @@
angular.module("admin.subscriptions").controller "OrdersPanelController", ($scope, OrderCycles) ->
$scope.subscription = $scope.object
$scope.cancelOrder = (order) ->
if confirm(t('are_you_sure'))
$scope.subscription.cancelOrder(order)
$scope.resumeOrder = (order) ->
if confirm(t('are_you_sure'))
$scope.subscription.resumeOrder(order)
$scope.orderCycleName = (id) ->
OrderCycles.byID[id].name
$scope.orderCycleCloses = (id) ->
oc = OrderCycles.byID[id]
return t('js.subscriptions.close_date_not_set') unless oc?.orders_close_at?
closes_at = moment(oc.orders_close_at)
text = if closes_at > moment() then t('js.subscriptions.closes') else t('js.subscription.closed')
"#{text} #{closes_at.fromNow()}"
$scope.stateText = (state) -> t("spree.order_state.#{state}")

View File

@@ -0,0 +1,13 @@
angular.module("admin.subscriptions").controller "ProductsController", ($scope, StatusMessage) ->
$scope.registerNextCallback 'products', ->
$scope.subscription_form.$submitted = true
if $scope.subscription.subscription_line_items.length > 0
$scope.subscription_form.$setPristine()
StatusMessage.clear()
$scope.setView('review')
else
StatusMessage.display 'failure', 'Please add at least one product'
$scope.registerBackCallback 'products', ->
StatusMessage.clear()
$scope.setView('address')

View File

@@ -0,0 +1,23 @@
angular.module("admin.subscriptions").controller "ProductsPanelController", ($scope, Subscriptions, StatusMessage) ->
$scope.subscription = $scope.object
$scope.distributor_id = $scope.subscription.shop_id
$scope.saving = false
$scope.saved = ->
pristine = Subscriptions.pristineByID[$scope.subscription.id].subscription_line_items
return false unless angular.equals($scope.subscription.subscription_line_items, pristine)
true
$scope.save = ->
$scope.saving = true
StatusMessage.display 'progress', 'Saving...'
$scope.subscription.update().then (response) ->
$scope.saving = false
StatusMessage.display 'success', 'Saved'
, (response) ->
$scope.saving = false
if response.data?.errors?
keys = Object.keys(response.data.errors)
StatusMessage.display 'failure', response.data.errors[keys[0]][0]
else
StatusMessage.display 'success', 'Saved'

View File

@@ -0,0 +1,8 @@
angular.module("admin.subscriptions").controller "ReviewController", ($scope, Customers, Schedules, PaymentMethods, ShippingMethods) ->
$scope.formatAddress = (a) ->
formatted = []
formatted.push "#{a.firstname} #{a.lastname}"
formatted.push a.address1
formatted.push a.city
formatted.push a.zipcode
formatted.join(", ")

View File

@@ -0,0 +1,27 @@
angular.module("admin.subscriptions").controller "SubscriptionController", ($scope, Subscription, SubscriptionForm, Customers, Schedules, PaymentMethods, ShippingMethods) ->
$scope.subscription = new Subscription()
$scope.errors = null
$scope.save = null
$scope.customers = Customers.all
$scope.schedules = Schedules.all
$scope.paymentMethods = PaymentMethods.all
$scope.shippingMethods = ShippingMethods.all
$scope.distributor_id = $scope.subscription.shop_id # variant selector requires distributor_id
$scope.view = if $scope.subscription.id? then 'review' else 'details'
$scope.nextCallbacks = {}
$scope.backCallbacks = {}
$scope.creditCards = []
$scope.setView = (view) -> $scope.view = view
$scope.stepTitleFor = (step) -> t("admin.subscriptions.steps.#{step}")
$scope.registerNextCallback = (view, callback) => $scope.nextCallbacks[view] = callback
$scope.registerBackCallback = (view, callback) => $scope.backCallbacks[view] = callback
$scope.next = -> $scope.nextCallbacks[$scope.view]()
$scope.back = -> $scope.backCallbacks[$scope.view]()
$scope.shipAddressFromBilling = =>
angular.extend($scope.subscription.ship_address, $scope.subscription.bill_address)
$scope.$watch 'subscription_form', ->
form = new SubscriptionForm($scope.subscription_form, $scope.subscription)
$scope.errors = form.errors
$scope.save = form.save

View File

@@ -0,0 +1,24 @@
angular.module("admin.subscriptions").controller "SubscriptionLineItemsController", ($scope, InfoDialog) ->
$scope.newItem = { variant_id: 0, quantity: 1 }
$scope.addSubscriptionLineItem = ->
match = $scope.match()
if match
if match._destroy
angular.extend(match, $scope.newItem)
delete match._destroy
else
InfoDialog.open 'error', t('admin.subscriptions.product_already_in_order')
else
$scope.subscription_form.$setDirty()
$scope.subscription.buildItem($scope.newItem)
$scope.removeSubscriptionLineItem = (item) ->
$scope.subscription_form.$setDirty()
$scope.subscription.removeItem(item)
$scope.match = ->
matching = $scope.subscription.subscription_line_items.filter (sli) ->
sli.variant_id == $scope.newItem.variant_id
return matching[0] if matching.length > 0
null

View File

@@ -0,0 +1,20 @@
angular.module("admin.subscriptions").controller "SubscriptionsController", ($scope, Subscriptions, Columns, RequestMonitor, shops, ShippingMethods, PaymentMethods) ->
$scope.columns = Columns.columns
$scope.shops = shops
$scope.shop_id = if shops.length == 1 then shops[0].id else null
$scope.shippingMethodsByID = ShippingMethods.byID
$scope.paymentMethodsByID = PaymentMethods.byID
$scope.RequestMonitor = RequestMonitor
$scope.query = ''
$scope.$watch "shop_id", ->
if $scope.shop_id?
$scope.subscriptions = Subscriptions.index("q[shop_id_eq]": $scope.shop_id, "q[canceled_at_null]": true)
$scope.itemCount = (subscription) ->
subscription.subscription_line_items.reduce (sum, sli) ->
return sum + sli.quantity
, 0
$scope.filtersApplied = ->
$scope.query != ''

View File

@@ -0,0 +1,9 @@
# Used to display a message before redirecting to a link
angular.module("admin.subscriptions").directive "confirmOrderEdit", (ConfirmDialog, $window) ->
restrict: "A"
link: (scope, element, attrs) ->
element.bind "click", (event) ->
unless scope.proxyOrder.order_id?
event.preventDefault()
ConfirmDialog.open('error', t('admin.subscriptions.orders.confirm_edit'), {confirm: t('admin.subscriptions.yes_i_am_sure')}).then ->
$window.open(attrs.href)

View File

@@ -0,0 +1,28 @@
angular.module("admin.subscriptions").directive 'newSubscriptionDialog', ($compile, $window, $templateCache, DialogDefaults, shops) ->
restrict: 'A'
scope: true
link: (scope, element, attr) ->
scope.submitted = false
scope.shops = shops
scope.shop_id = null
scope.newSubscription = ->
scope.new_subscription_form.$setPristine()
scope.submitted = true
if scope.shop_id?
$window.location.href = "/admin/subscriptions/new?subscription[shop_id]=#{scope.shop_id}"
return
# Compile modal template
template = $compile($templateCache.get('admin/new_subscription_dialog.html'))(scope)
# Set Dialog options
template.dialog(DialogDefaults)
# Link opening of dialog to click event on element
element.bind 'click', (e) ->
if shops.length == 1
scope.shop_id = shops[0].id
scope.newSubscription()
else
template.dialog('open')

View File

@@ -0,0 +1,5 @@
angular.module("admin.subscriptions").factory 'CreditCardResource', ($resource) ->
resource = $resource '/admin/customers/:customer_id/cards.json', {},
'index':
method: 'GET'
isArray: true

View File

@@ -0,0 +1,6 @@
angular.module("admin.subscriptions").factory "Subscription", ($injector, SubscriptionResource) ->
class Subscription extends SubscriptionResource
constructor: ->
if $injector.has('subscription')
angular.extend(@, $injector.get('subscription'))

View File

@@ -0,0 +1,77 @@
# Wrapper for actions provided by ngResource
# Used to extend the prototype of the subscription resource created by SubscriptionResource
angular.module("admin.subscriptions").factory 'SubscriptionActions', ($http, $injector, $q, InfoDialog, ConfirmDialog) ->
buildItem: (item) ->
return false unless item.variant_id > 0
return false unless item.quantity > 0
data = angular.extend({}, item, { shop_id: @shop_id, schedule_id: @schedule_id })
$http.post("/admin/subscription_line_items/build", data).then (response) =>
@subscription_line_items.push response.data
, (response) =>
InfoDialog.open 'error', response.data.errors[0]
removeItem: (item) ->
item._destroy = true
create: ->
@$save().then (response) =>
$injector.get('Subscriptions').afterCreate(@id) if $injector.has('Subscriptions')
$q.resolve(response)
, (response) => $q.reject(response)
update: ->
@$update().then (response) =>
$injector.get('Subscriptions').afterUpdate(@id) if $injector.has('Subscriptions')
orders_with_issues = @not_closed_proxy_orders.filter((po) -> po.update_issues.length > 0)
if orders_with_issues.length > 0
InfoDialog.open('error', null, 'admin/order_update_issues_dialog.html', { proxyOrders: orders_with_issues})
return $q.reject(response)
$q.resolve(response)
, (response) => $q.reject(response)
cancel: ->
ConfirmDialog.open('error', t('admin.subscriptions.confirm_cancel_msg'), {cancel: t('back'), confirm: t('admin.subscriptions.yes_i_am_sure')})
.then =>
@$cancel().then angular.noop, (response) =>
if response.data?.errors?.open_orders?
options = {cancel: t('admin.subscriptions.no_keep_them'), confirm: t('admin.subscriptions.yes_cancel_them')}
ConfirmDialog.open('error', response.data.errors.open_orders, options)
.then (=> @$cancel(open_orders: 'cancel')), (=> @$cancel(open_orders: 'keep'))
else
InfoDialog.open 'error', t('admin.subscriptions.cancel_failure_msg')
pause: ->
ConfirmDialog.open('error', t('admin.subscriptions.confirm_pause_msg'), {confirm: t('admin.subscriptions.yes_i_am_sure')})
.then =>
@$pause().then angular.noop, (response) =>
if response.data?.errors?.open_orders?
options = {cancel: t('admin.subscriptions.no_keep_them'), confirm: t('admin.subscriptions.yes_cancel_them')}
ConfirmDialog.open('error', response.data.errors.open_orders, options)
.then (=> @$pause(open_orders: 'cancel')), (=> @$pause(open_orders: 'keep'))
else
InfoDialog.open 'error', t('admin.subscriptions.pause_failure_msg')
unpause: ->
ConfirmDialog.open('error', t('admin.subscriptions.confirm_unpause_msg'), {confirm: t('admin.subscriptions.yes_i_am_sure')})
.then =>
@$unpause().then angular.noop, (response) =>
if response.data?.errors?.canceled_orders?
InfoDialog.open('info', response.data.errors.canceled_orders)
.then (=> @$unpause(canceled_orders: 'notified'))
else
InfoDialog.open 'error', t('admin.subscriptions.unpause_failure_msg')
cancelOrder: (order) ->
if order.id?
$http.put("/admin/proxy_orders/#{order.id}/cancel").then (response) =>
angular.extend(order,response.data)
, (response) ->
InfoDialog.open 'error', response.data.errors[0]
resumeOrder: (order) ->
if order.id?
$http.put("/admin/proxy_orders/#{order.id}/resume").then (response) =>
angular.extend(order,response.data)
, (response) ->
InfoDialog.open 'error', response.data.errors[0]

View File

@@ -0,0 +1,35 @@
angular.module("admin.subscriptions").factory 'SubscriptionForm', ($window, StatusMessage) ->
class SubscriptionForm
form: null
subscription: null
errors: {}
constructor: (form, subscription) ->
@form = form
@subscription = subscription
save: =>
return @formInvalid() unless @form.$valid
delete @errors[k] for k, v of @errors
@form.$setPristine()
StatusMessage.display 'progress', 'Saving...'
if @subscription.id?
@subscription.update().then @successCallback, @errorCallback
else
@subscription.create().then @successCallback, @errorCallback
successCallback: (response) =>
StatusMessage.display 'success', 'Saved. Redirecting...'
$window.location.href = "/admin/subscriptions"
errorCallback: (response) =>
if response.data?.errors?
angular.extend(@errors, response.data.errors)
keys = Object.keys(response.data.errors)
StatusMessage.display 'failure', response.data.errors[keys[0]][0]
else
# Happens when there are sync issues between SO and initialised orders
# We save the SO, but open a dialog, so want to stay on the page
StatusMessage.display 'success', 'Saved'
formInvalid: -> StatusMessage.display 'failure', t('admin.subscriptions.details.invalid_error')

View File

@@ -0,0 +1,35 @@
# Provides additional auxillary functions to instances of SubscriptionResource
# Used to extend the extend the protype of the subscription resource created by SubscriptionResource
angular.module("admin.subscriptions").factory 'SubscriptionFunctions', ($injector) ->
estimatedSubtotal: ->
@subscription_line_items.reduce (subtotal, item) ->
return subtotal if item._destroy
subtotal += item.price_estimate * item.quantity
, 0
estimatedFees: ->
@shipping_fee_estimate + @payment_fee_estimate
estimatedTotal: ->
@estimatedSubtotal() + @estimatedFees()
customer: ->
return unless @customer_id
return unless $injector.has('Customers')
$injector.get('Customers').byID[@customer_id]
schedule: ->
return unless @schedule_id
return unless $injector.has('Schedules')
$injector.get('Schedules').byID[@schedule_id]
paymentMethod: ->
return unless @payment_method_id
return unless $injector.has('PaymentMethods')
$injector.get('PaymentMethods').byID[@payment_method_id]
shippingMethod: ->
return unless @shipping_method_id
return unless $injector.has('ShippingMethods')
$injector.get('ShippingMethods').byID[@shipping_method_id]

View File

@@ -0,0 +1,32 @@
angular.module("admin.subscriptions").factory 'SubscriptionResource', ($resource, SubscriptionActions, SubscriptionFunctions) ->
resource = $resource('/admin/subscriptions/:id/:action.json', {}, {
'index':
method: 'GET'
isArray: true
'update':
method: 'PUT'
params:
id: '@id'
'cancel':
method: 'PUT'
params:
id: '@id'
action: 'cancel'
open_orders: '@open_orders'
'pause':
method: 'PUT'
params:
id: '@id'
action: 'pause'
open_orders: '@open_orders'
'unpause':
method: 'PUT'
params:
id: '@id'
action: 'unpause'
})
angular.extend(resource.prototype, SubscriptionActions)
angular.extend(resource.prototype, SubscriptionFunctions)
resource

View File

@@ -0,0 +1,27 @@
angular.module("admin.subscriptions").factory 'Subscriptions', ($q, SubscriptionResource, Subscription, RequestMonitor) ->
new class Subscriptions
byID: {}
pristineByID: {}
index: (params={}, callback=null) ->
request = SubscriptionResource.index params, (data) => @load(data)
RequestMonitor.load(request.$promise)
request
load: (subscriptions) ->
for subscription in subscriptions
@byID[subscription.id] = subscription
@pristineByID[subscription.id] = angular.copy(subscription)
afterCreate: (id) ->
return unless @byID[id]?
@pristineByID[id] = angular.copy(@byID[id])
afterUpdate: (id) ->
return unless @byID[id]?
@pristineByID[id] = angular.copy(@byID[id])
afterRemoveItem: (id, deletedItemID) ->
return unless @pristineByID[id]?
for item, i in @pristineByID[id].subscription_line_items when item.id == deletedItemID
@pristineByID[id].subscription_line_items.splice(i, 1)

View File

@@ -0,0 +1 @@
angular.module("admin.subscriptions", ['ngResource','admin.indexUtils','admin.dropdown'])

View File

@@ -1,6 +1,6 @@
$(document).ready(function() {
$('.datetimepicker').datetimepicker({
dateFormat: Spree.translations.date_picker,
dateFormat: 'yy-mm-dd',
dayNames: Spree.translations.abbr_day_names,
dayNamesMin: Spree.translations.abbr_day_names,
monthNames: Spree.translations.month_names,

View File

@@ -14,8 +14,11 @@ angular.module("admin.utils").directive "ofnSelect2", ($sanitize, $timeout, $fil
scope.text ?= 'name'
scope.multiple ?= false
scope.filter ?= -> true
scope.placeholder ?= t('admin.choose')
if scope.data.$promise
# Initialize with empty data set, while we wait for data
element.select2(data:[], placeholder: scope.placeholder)
scope.data.$promise.then -> init()
else
init()
@@ -39,6 +42,7 @@ angular.module("admin.utils").directive "ofnSelect2", ($sanitize, $timeout, $fil
item.name = $sanitize(item.name) for item in scope.data
element.select2
multiple: scope.multiple
placeholder: scope.placeholder
minimumResultsForSearch: scope.minSearch || 0
data: ->
filtered = $filter('filter')(scope.data,scope.filter)

View File

@@ -0,0 +1,33 @@
angular.module("admin.utils").directive "variantAutocomplete", ($timeout) ->
restrict: 'C'
link: (scope, element, attrs) ->
# Make variantAutocomplete do nothing because it is called
# from core/app/assets/javascripts/admin/orders/edit.js
$.fn.variantAutocomplete = angular.noop
$timeout ->
if $("#variant_autocomplete_template").length > 0
variantTemplate = Handlebars.compile($("#variant_autocomplete_template").text())
if Spree.routes
element.parent().children(".options_placeholder").attr "id", element.parent().data("index")
element.select2
placeholder: "Select a variant"
minimumInputLength: 3
quietMillis: 300
ajax:
url: Spree.routes.variants_search
datatype: "json"
data: (term, page) ->
q: term
distributor_id: scope.distributor_id
order_cycle_id: scope.order_cycle_id
results: (data, page) ->
results: data
formatResult: (variant) ->
if variant["images"][0] != undefined && variant["images"][0].image != undefined
variant.image = variant.images[0].image.mini_url
variantTemplate variant: variant
formatSelection: (variant) ->
element.parent().children(".options_placeholder").html variant.options_text
variant.name

View File

@@ -0,0 +1,21 @@
angular.module("admin.utils").factory 'ConfirmDialog', ($rootScope, $q, $compile, $templateCache, DialogDefaults) ->
new class ConfirmDialog
open: (type, message, options) ->
deferred = $q.defer()
scope = $rootScope.$new()
scope.message = message
scope.dialog_class = type
scope.confirmText = options?.confirm || t('ok')
scope.cancelText = options?.cancel || t('cancel')
template = $compile($templateCache.get('admin/confirm_dialog.html'))(scope)
template.dialog(DialogDefaults)
template.dialog('open')
scope.confirm = ->
deferred.resolve()
template.dialog('close')
null
scope.close = ->
deferred.reject()
template.dialog('close')
null
deferred.promise

View File

@@ -3,7 +3,8 @@ angular.module("admin.utils").factory "DialogDefaults", ($window) ->
hide: { effect: "fade", duration: 300 }
autoOpen: false
resizable: false
width: $window.innerWidth * 0.4;
width: $window.innerWidth * 0.4
position: ['middle', 100]
modal: true
open: (event, ui) ->
$('.ui-widget-overlay').bind 'click', ->

View File

@@ -1,12 +1,22 @@
angular.module("admin.customers").factory 'InfoDialog', ($rootScope, $compile, $injector, $templateCache, DialogDefaults) ->
angular.module("admin.utils").factory 'InfoDialog', ($rootScope, $q, $compile, $templateCache, DialogDefaults) ->
new class InfoDialog
open: (type, message) ->
icon_classes: {
error: 'icon-exclamation-sign'
info: 'icon-info-sign'
}
open: (type, message, templateUrl='admin/info_dialog.html', options={}) ->
deferred = $q.defer()
scope = $rootScope.$new()
scope.message = message
scope.dialog_class = type
template = $compile($templateCache.get('admin/info_dialog.html'))(scope)
scope.icon_class = @icon_classes[type]
scope.options = options
template = $compile($templateCache.get(templateUrl))(scope)
template.dialog(DialogDefaults)
template.dialog('open')
scope.close = ->
deferred.resolve()
template.dialog('close')
null
deferred.promise

View File

@@ -1 +1 @@
angular.module("admin.utils", ["templates", "ngSanitize"])
angular.module("admin.utils", ["templates", "ngSanitize"]).config ($httpProvider) ->

View File

@@ -1,30 +0,0 @@
$(document).ready ->
if $("#variant_autocomplete_template").length > 0
window.variantTemplate = Handlebars.compile($("#variant_autocomplete_template").text())
formatVariantResult = (variant) ->
if variant["images"][0] != undefined && variant["images"][0].image != undefined
variant.image = variant.images[0].image.mini_url
variantTemplate variant: variant
$.fn.variantAutocomplete = ->
if Spree.routes
@parent().children(".options_placeholder").attr "id", @parent().data("index")
@select2
placeholder: "Select a variant"
minimumInputLength: 3
ajax:
url: Spree.routes.variants_search
datatype: "json"
data: (term, page) ->
q: term
distributor_id: $("#order_distributor_id").val()
order_cycle_id: $("#order_order_cycle_id").val()
results: (data, page) ->
results: data
formatResult: formatVariantResult
formatSelection: (variant) ->
$(@element).parent().children(".options_placeholder").html variant.options_text
variant.name

View File

@@ -23,7 +23,16 @@
#
#= require angular-backstretch.js
#= require angular-flash.min.js
#
#= require moment
#= require moment/en-gb.js
#= require moment/es.js
#= require moment/fr.js
#= require moment/it.js
#= require moment/nb.js
#= require moment/pt-br.js
#= require moment/sv.js
#
#= require modernizr
#
#= require foundation

View File

@@ -1,4 +1,4 @@
Darkswarm.controller "LoginCtrl", ($scope, $http, $window, AuthenticationService, Redirections, Loading) ->
Darkswarm.controller "LoginCtrl", ($scope, $timeout, $location, $http, $window, AuthenticationService, Redirections, Loading) ->
$scope.path = "/login"
$scope.submit = ->
@@ -10,4 +10,18 @@ Darkswarm.controller "LoginCtrl", ($scope, $http, $window, AuthenticationService
$window.location.href = $window.location.origin + $window.location.pathname # Strips out hash fragments
.error (data) ->
Loading.clear()
$scope.errors = data.message
$scope.errors = data.message || data.error
$scope.user_unconfirmed = (data.error == t('devise.failure.unconfirmed'))
$scope.resend_confirmation = ->
$http.post("/user/spree_user/confirmation", {spree_user: $scope.spree_user}).success (data)->
$scope.messages = t('devise.confirmations.send_instructions')
.error (data) ->
$scope.errors = t('devise.confirmations.failed_to_send')
$timeout ->
if angular.isDefined($location.search()['validation'])
if $location.search()['validation'] == 'confirmed'
$scope.messages = t('devise.confirmations.confirmed')
if $location.search()['validation'] == 'not_confirmed'
$scope.errors = t('devise.confirmations.not_confirmed')

View File

@@ -8,10 +8,8 @@ Darkswarm.controller "SignupCtrl", ($scope, $http, $window, $location, Redirecti
password: null
$scope.submit = ->
$http.post("/user/spree_user", {spree_user: $scope.spree_user}).success (data)->
if Redirections.after_login
$window.location.href = $window.location.origin + Redirections.after_login
else
$window.location.href = $window.location.origin + $window.location.pathname # Strips out hash fragments
$http.post("/user/spree_user", {spree_user: $scope.spree_user, return_url: $location.absUrl()}).success (data)->
$scope.errors = {email: null, password: null}
$scope.messages = t('devise.user_registrations.spree_user.signed_up_but_unconfirmed')
.error (data) ->
$scope.errors = data

View File

@@ -1,6 +1,3 @@
# Old aliases before i18n-js was introduced.
# TODO - delete it after everything is moved to i18n-js
# Declares the translation function t.
# You can use translate('login') or t('login') in Javascript.
window.translate = (key, options = {}) ->

View File

@@ -4,10 +4,8 @@ Darkswarm.factory "AuthenticationService", (Navigation, $modal, $location, Redir
selectedPath: "/login"
constructor: ->
if $location.path() in ["/login", "/signup", "/forgot"] && location.pathname isnt '/register/auth'
@open $location.path()
else if location.pathname is '/register/auth'
@open '/signup', 'registration_authentication.html'
if $location.path() in ["/login", "/signup", "/forgot"] || location.pathname is '/register/auth'
@open @initialTab(), @initialTemplate()
open: (path = false, template = 'authentication.html') =>
@modalInstance = $modal.open
@@ -17,6 +15,23 @@ Darkswarm.factory "AuthenticationService", (Navigation, $modal, $location, Redir
@selectedPath = path || @selectedPath
Navigation.navigate @selectedPath
# Opens the /login tab if returning from email confirmation,
# the /signup tab if opened from the enterprise registration page,
# otherwise opens whichever tab is selected in the URL params ('/login', '/signup', or '/forgot')
initialTab: ->
if angular.isDefined($location.search()['validation'])
'/login'
else if location.pathname is '/register/auth'
'/signup'
else
$location.path()
# Loads the registration page modal when needed, otherwise the default modal
initialTemplate: ->
if location.pathname is '/register/auth'
'registration_authentication.html'
else
'authentication.html'
select: (path)=>
@selectedPath = path

View File

@@ -2,7 +2,6 @@ Darkswarm.factory "EnterpriseRegistrationService", ($http, RegistrationService,
new class EnterpriseRegistrationService
enterprise:
user_ids: [CurrentUser.id]
email: CurrentUser.email
email_address: CurrentUser.email
address: {}
country: availableCountries[0]

View File

@@ -0,0 +1,8 @@
#confirm-dialog{ ng: { class: "dialog_class" } }
.message.clearfix.margin-bottom-30
.icon.text-center
%i.icon-question-sign
.text{ ng: { bind: "::message" } }
.action-buttons.text-center
%button.cancel{ ng: { click: "close()", bind: "::cancelText" } }
%button.confirm.red{ ng: { click: "confirm()", bind: "::confirmText" } }

View File

@@ -2,7 +2,7 @@
%h2 {{ addressType === 'bill_address' ? "#{t('admin.customers.index.edit_bill_address')}" : "#{t('admin.customers.index.edit_ship_address')}" }}
%form{ name: 'edit_address_form', novalidate: true, ng: { submit: 'updateAddress()'}}
.row
= t('admin.customers.index.required_fileds')
{{ 'admin.customers.index.required_fileds' | t }}
(
%span.required *
)
@@ -11,67 +11,64 @@
%table.no-borders
%tr
%td{style: 'width: 30%'}
= t('spree.firstname')
{{ 'first_name' | t }}
%span.required *
%td
%input{ type: 'text', name: 'firstname', required: true, ng: { model: 'address.firstname'} }
%tr
%td
= t('spree.lastname')
{{ 'last_name' | t }}
%span.required *
%td
%input{ type: 'text', name: 'lastname', required: true, ng: { model: 'address.lastname'} }
%tr
%td
= t('spree.street_address')
{{ 'address' | t }}
%span.required *
%td
%input{ type: 'text', name: 'address1', required: true, ng: { model: 'address.address1'} }
%tr
%td
= t('spree.street_address_1')
{{ 'address2' | t }}
%td
%input{ type: 'text', name: 'address2', ng: { model: 'address.address2'} }
%tr
%td
= t('spree.city')
{{ 'city' | t }}
%span.required *
%td
%input{ type: 'text', name: 'city', required: true, ng: { model: 'address.city'} }
%tr
%td
= t('spree.zipcode')
{{ 'postcode' | t }}
%span.required *
%td
%input{ type: 'text', name: 'zipcode', required: true, ng: { model: 'address.zipcode'} }
%tr
%td
= t('spree.country')
{{ 'country' | t }}
%span.required *
%td
%select{ name: 'country', required: true, ng: { model: 'address.country_id' } }
%option{value: ''}
= t('admin.customers.index.select_country')
%option{ ng: { repeat: 'country in availableCountries' }, value: '{{country.id}}' }
{{country.name}}
%input.ofn-select2.fullwidth#country_id{ type: 'number',
name: 'country_id', required: true,
placeholder: "{{ 'admin.customers.index.select_country' | t }}",
data: 'availableCountries', ng: { model: 'address.country_id' } }
%tr
%td
= t('spree.state')
{{ 'state' | t }}
%span.required *
%td
%select{ name: 'state', required: true, ng: { model: 'address.state_id' } }
%option{value: ''}
= t('admin.customers.index.select_state')
%option{ ng: { repeat: 'state in states' }, value: '{{state.id}}' }
{{state.name}}
%input.ofn-select2.fullwidth#state_id{ type: 'number',
name: 'state_id', required: true,
placeholder: "{{ 'admin.customers.index.select_state' | t }}",
data: 'states', ng: { model: 'address.state_id' } }
%tr
%td
= t('spree.phone')
{{ 'phone' | t }}
%span.required *
%td
%input{ type: 'text', name: 'phone', required: true, ng: { model: 'address.phone'} }
.text-center
%input.button.red.icon-plus{ type: 'submit', value: t('admin.customers.index.update_address')}

View File

@@ -1,7 +1,7 @@
#info-dialog{ ng: { class: "dialog_class" } }
.message.clearfix.margin-bottom-30
.icon.text-center
%i.icon-exclamation-sign
%i{ ng: { class: "icon_class" } }
.text
{{ message }}
.action-buttons.text-center

View File

@@ -1,7 +1,7 @@
.ofn-drop-down
%span
%i.icon-check
= t('admin.actions')
{{ 'admin.actions' | t }}
%i{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" }
%div.menu{ 'ng-show' => "expanded" }
%a.menu_item{ 'ng-repeat' => "link in links", href: '{{link.url}}', target: "{{link.target || '_self'}}", data: { method: "{{ link.method || 'get' }}", confirm: "{{link.confirm}}" } }

View File

@@ -1,19 +1,25 @@
#tag-rule-help
.margin-bottom-30.text-center
.text-big
= t('js.admin.modals.tag_rule_help.title')
{{ 'js.admin.modals.tag_rule_help.title' | t }}
.margin-bottom-30
.text-normal= t('js.admin.modals.tag_rule_help.overview')
%p= t('js.admin.modals.tag_rule_help.overview_text')
.text-normal
{{ 'js.admin.modals.tag_rule_help.overview' | t }}
%p
{{ 'js.admin.modals.tag_rule_help.overview_text' | t }}
.margin-bottom-30
.text-normal= t('js.admin.modals.tag_rule_help.by_default_rules')
%p= t('js.admin.modals.tag_rule_help.by_default_rules_text')
.text-normal
{{ 'js.admin.modals.tag_rule_help.by_default_rules' | t }}
%p
{{ 'js.admin.modals.tag_rule_help.by_default_rules_text' | t }}
.margin-bottom-30
.text-normal= t('js.admin.modals.tag_rule_help.customer_tagged_rules')
%p= t('js.admin.modals.tag_rule_help.customer_tagged_rules_text')
.text-normal
{{ 'js.admin.modals.tag_rule_help.customer_tagged_rules' | t }}
%p
{{ 'js.admin.modals.tag_rule_help.customer_tagged_rules_text' | t }}
.text-center
%input.button.red.icon-plus{ type: 'button', value: t('js.admin.modals.got_it'), ng: { click: 'close()' } }

View File

@@ -1,6 +1,6 @@
#new-customer-dialog
.text-normal.margin-bottom-30.text-center
= t('admin.customers.index.add_a_new_customer_for', shop_name: "{{ CurrentShop.shop.name }}:")
{{ 'admin.customers.index.add_a_new_customer_for' | t:{ shop_name: CurrentShop.shop.name } }}
%form{ name: 'new_customer_form', novalidate: true, ng: { submit: "addCustomer()" }}
@@ -8,7 +8,7 @@
%input.fullwidth{ type: 'email', name: 'email', required: true, placeholder: t('admin.customers.index.customer_placeholder'), ng: { model: "email" } }
%div{ ng: { show: "submitted && new_customer_form.$pristine" } }
.error{ ng: { show: "(new_customer_form.email.$error.email || new_customer_form.email.$error.required)" } }
= t('admin.customers.index.valid_email_error')
{{ 'admin.customers.index.valid_email_error' | t }}
.error{ ng: { repeat: "error in errors", bind: "error" } }
.text-center

View File

@@ -0,0 +1,14 @@
#new-subscription-dialog
.text-normal.margin-bottom-30.text-center
= t('admin.subscriptions.index.please_select_a_shop')
%form{ name: 'new_subscription_form', novalidate: true, ng: { submit: "newSubscription()" }}
.text-center.margin-bottom-30
%input.ofn-select2.fullwidth#new_subscription_shop_id{ ng: { model: 'shop_id' }, required: true, name: 'shop_id', data: 'shops' }
%div{ ng: { show: "submitted && new_subscription_form.$pristine" } }
.error{ ng: { show: "new_subscription_form.shop_id.$error.required" } }
= t('admin.subscriptions.index.please_select_a_shop')
.text-center
%input.button.red.icon-plus{ type: 'submit', value: t('continue') }

View File

@@ -1,6 +1,6 @@
#new-tag-rule-dialog
.text-normal.margin-bottom-30.text-center
= t('js.admin.new_tag_rule_dialog.select_rule_type')
{{ 'js.admin.new_tag_rule_dialog.select_rule_type' | t }}
.text-center.margin-bottom-30
-# %select.fullwidth{ 'select2-min-search' => 5, 'ng-model' => 'newRuleType', 'ng-options' => 'ruleType.id as ruleType.name for ruleType in availableRuleTypes' }

View File

@@ -0,0 +1,18 @@
%table
%tr
%td#available-order-cycles
Available
.order-cycles
.order-cycle{ ng: { repeat: 'orderCycle in orderCycles | available:selectedOrderCycles as availableOrderCycles', click: 'selections.available = orderCycle', dblclick: 'add(orderCycle)', class: '{selected: selections.available == orderCycle}' } }
{{ orderCycle.name }}
%td#add-remove-buttons
%a.add.button{ href: 'javascript:void(0)', ng: { click: 'add()' } }
%i.icon-chevron-right
%a.remove.button{ href: 'javascript:void(0)', ng: { click: 'remove()' } }
%i.icon-chevron-left
%td#selected-order-cycles
Selected
.order-cycles
.order-cycle{ ng: { repeat: 'orderCycle in selectedOrderCycles', click: 'selections.selected = orderCycle', dblclick: 'remove(orderCycle)', class: '{selected: selections.selected == orderCycle}' } }
{{ orderCycle.name }}
.error{ ng: { repeat: "error in errors", bind: "error" } }

View File

@@ -2,128 +2,162 @@
.alpha.eight.columns
%div{ ng: { if: "!enterprise.is_primary_producer", switch: "enterprise.sells" } }
.info{ ng: { switch: { when: "none" } } }
%h3= t('js.admin.panels.enterprise_package.hub_profile')
%h3
{{ 'js.admin.panels.enterprise_package.hub_profile' | t }}
%p
%strong= t('js.admin.panels.enterprise_package.hub_profile_cost')
%strong
{{ 'js.admin.panels.enterprise_package.hub_profile_cost' | t }}
%p= t('js.admin.panels.enterprise_package.hub_profile_text1')
%p
{{ 'js.admin.panels.enterprise_package.hub_profile_text1' | t }}
%p= t('js.admin.panels.enterprise_package.hub_profile_text2')
%p
{{ 'js.admin.panels.enterprise_package.hub_profile_text2' | t }}
.info{ ng: { switch: { when: "any" } } }
%h3= t('js.admin.panels.enterprise_package.hub_shop')
%h3
{{ 'js.admin.panels.enterprise_package.hub_shop' | t }}
%p
%strong
%monthly-pricing-description{ joiner: "comma" }
%p= t('js.admin.panels.enterprise_package.hub_shop_text1')
%p
{{ 'js.admin.panels.enterprise_package.hub_shop_text1' | t }}
%p= t('js.admin.panels.enterprise_package.hub_shop_text2')
%p
{{ 'js.admin.panels.enterprise_package.hub_shop_text2' | t }}
%p= t('js.admin.panels.enterprise_package.hub_shop_text3')
%p
{{ 'js.admin.panels.enterprise_package.hub_shop_text3' | t }}
.info{ ng: { switch: { default: true } } }
%h3
= t('js.admin.panels.enterprise_package.choose_package')
{{ 'js.admin.panels.enterprise_package.choose_package' | t }}
%i.icon-arrow-right
%p
%strong= t('js.admin.panels.enterprise_package.choose_package_text1')
%strong
{{ 'js.admin.panels.enterprise_package.choose_package_text1' | t }}
%p
= t('js.admin.panels.enterprise_package.choose_package_text2')
{{ 'js.admin.panels.enterprise_package.choose_package_text2' | t }}
%div{ ng: { if: "enterprise.is_primary_producer", switch: "enterprise.sells" } }
.info{ ng: { switch: { when: "none" } } }
%h3= t('js.admin.panels.enterprise_package.profile_only')
%h3
{{ 'js.admin.panels.enterprise_package.profile_only' | t }}
%p
%strong= t('js.admin.panels.enterprise_package.profile_only_cost')
%strong
{{ 'js.admin.panels.enterprise_package.profile_only_cost' | t }}
%p= t('js.admin.panels.enterprise_package.profile_only_text1')
%p
{{ 'js.admin.panels.enterprise_package.profile_only_text1' | t }}
%p= t('js.admin.panels.enterprise_package.profile_only_text2')
%p
{{ 'js.admin.panels.enterprise_package.profile_only_text2' | t }}
%p= t('js.admin.panels.enterprise_package.profile_only_text3')
%p
{{ 'js.admin.panels.enterprise_package.profile_only_text3' | t }}
.info{ ng: { switch: { when: "own" } } }
%h3= t('js.admin.panels.enterprise_package.producer_shop')
%h3
{{ 'js.admin.panels.enterprise_package.producer_shop' | t }}
%p
%strong
%monthly-pricing-description{ joiner: "comma" }
%p= t('js.admin.panels.enterprise_package.producer_shop_text1')
%p
{{ 'js.admin.panels.enterprise_package.producer_shop_text1' | t }}
%p= t('js.admin.panels.enterprise_package.producer_shop_text2')
%p
{{ 'js.admin.panels.enterprise_package.producer_shop_text2' | t }}
.info{ ng: { switch: { when: "any" } } }
%h3= t('js.admin.panels.enterprise_package.producer_hub')
%h3
{{ 'js.admin.panels.enterprise_package.producer_hub' | t }}
%p
%strong
%monthly-pricing-description{ joiner: "comma" }
%p= t('js.admin.panels.enterprise_package.producer_hub_text1')
%p
{{ 'js.admin.panels.enterprise_package.producer_hub_text1' | t }}
%p= t('js.admin.panels.enterprise_package.producer_hub_text2')
%p
{{ 'js.admin.panels.enterprise_package.producer_hub_text2' | t }}
%p= t('js.admin.panels.enterprise_package.producer_hub_text3')
%p
{{ 'js.admin.panels.enterprise_package.producer_hub_text3' | t }}
.info{ ng: { switch: { default: true } } }
%h3
= t('js.admin.panels.enterprise_package.choose_package')
{{ 'js.admin.panels.enterprise_package.choose_package' | t }}
%i.icon-arrow-right
%p
%strong= t('js.admin.panels.enterprise_package.choose_package_text1')
%strong
{{ 'js.admin.panels.enterprise_package.choose_package_text1' | t }}
%p
= t('js.admin.panels.enterprise_package.choose_package_text2')
{{ 'js.admin.panels.enterprise_package.choose_package_text2' | t }}
.omega.eight.columns{ ng: { switch: "enterprise.is_primary_producer" } }
%div{ ng: { switch: { when: "false" } } }
%a.button.selector.hub-profile{ ng: { click: "enterprise.owned && (enterprise.sells='none')", class: "{selected: enterprise.sells=='none', disabled: !enterprise.owned}" } }
.top
%h3= t('js.admin.panels.enterprise_package.profile_only')
%p= t('js.admin.panels.enterprise_package.get_listing')
.bottom= t('js.admin.panels.enterprise_package.always_free')
%h3
{{ 'js.admin.panels.enterprise_package.profile_only' | t }}
%p
{{ 'js.admin.panels.enterprise_package.get_listing' | t }}
.bottom
{{ 'js.admin.panels.enterprise_package.always_free' | t }}
%a.button.selector.hub{ ng: { click: "enterprise.owned && (enterprise.sells='any')", class: "{selected: enterprise.sells=='any', disabled: !enterprise.owned}" } }
.top
%h3= t('js.admin.panels.enterprise_package.hub_shop')
%p= t('js.admin.panels.enterprise_package.sell_produce_others')
%h3
{{ 'js.admin.panels.enterprise_package.hub_shop' | t }}
%p
{{ 'js.admin.panels.enterprise_package.sell_produce_others' | t }}
.bottom
%monthly-pricing-description{ joiner: "newline" }
%div{ ng: { switch: { when: "true" } } }
%a.button.selector.producer-profile{ ng: { click: "enterprise.owned && (enterprise.sells='none')", class: "{selected: enterprise.sells=='none', disabled: !enterprise.owned}" } }
.top
%h3= t('js.admin.panels.enterprise_package.profile_only')
%p= t('js.admin.panels.enterprise_package.get_listing')
.bottom= t('js.admin.panels.enterprise_package.always_free')
%h3
{{ 'js.admin.panels.enterprise_package.profile_only' | t }}
%p
{{ 'js.admin.panels.enterprise_package.get_listing' | t }}
.bottom
{{ 'js.admin.panels.enterprise_package.always_free' | t }}
%a.button.selector.producer-shop{ ng: { click: "enterprise.owned && (enterprise.sells='own')", class: "{selected: enterprise.sells=='own', disabled: !enterprise.owned}" } }
.top
%h3= t('js.admin.panels.enterprise_package.producer_shop')
%p= t('js.admin.panels.enterprise_package.sell_own_produce')
%h3
{{ 'js.admin.panels.enterprise_package.producer_shop' | t }}
%p
{{ 'js.admin.panels.enterprise_package.sell_own_produce' | t }}
.bottom
%monthly-pricing-description{ joiner: "newline" }
%a.button.selector.producer-hub{ ng: { click: "enterprise.owned && (enterprise.sells='any')", class: "{selected: enterprise.sells=='any', disabled: !enterprise.owned}" } }
.top
%h3= t('js.admin.panels.enterprise_package.producer_hub')
%p= t('js.admin.panels.enterprise_package.sell_both')
%h3
{{ 'js.admin.panels.enterprise_package.producer_hub' | t }}
%p
{{ 'js.admin.panels.enterprise_package.sell_both' | t }}
.bottom
%monthly-pricing-description{ joiner: "newline" }
%a.button.update.fullwidth{ ng: { show: "enterprise.owned", class: "{disabled: saved() && !saving, saving: saving}", click: "save()" } }
%span{ ng: {hide: "saved() || saving" } }
= t('js.admin.panels.save')
{{ 'js.admin.panels.save' | t }}
%i.icon-save
%span{ ng: {show: "saved() && !saving" } }
= t('js.admin.panels.saved')
{{ 'js.admin.panels.saved' | t }}
%i.icon-ok-sign
%span{ ng: {show: "saving" } }
= t('js.admin.panels.saving')
{{ 'js.admin.panels.saving' | t }}
%i.icon-refresh

View File

@@ -1,37 +1,47 @@
.row.enterprise_producer_panel{ ng: { controller: 'indexProducerPanelCtrl' } }
.alpha.eight.columns
.info{ ng: { show: "enterprise.is_primary_producer==true" } }
%h3= t('js.admin.panels.enterprise_producer.producer')
%p= t('js.admin.panels.enterprise_producer.producer_text1')
%p= t('js.admin.panels.enterprise_producer.producer_text2')
%h3
{{ 'js.admin.panels.enterprise_producer.producer' | t }}
%p
{{ 'js.admin.panels.enterprise_producer.producer_text1' | t }}
%p
{{ 'js.admin.panels.enterprise_producer.producer_text2' | t }}
.info{ ng: { show: "enterprise.is_primary_producer==false" } }
%h3= t('js.admin.panels.enterprise_producer.non_producer')
%p= t('js.admin.panels.enterprise_producer.non_producer_text1')
%p= t('js.admin.panels.enterprise_producer.non_producer_text2')
%h3
{{ 'js.admin.panels.enterprise_producer.non_producer' | t }}
%p
{{ 'js.admin.panels.enterprise_producer.non_producer_text1' | t }}
%p
{{ 'js.admin.panels.enterprise_producer.non_producer_text2' | t }}
.omega.eight.columns
%a.button.selector.producer{ ng: { click: 'enterprise.owned && changeToProducer()', class: "{selected: enterprise.is_primary_producer==true, disabled: !enterprise.owned}" } }
.top
%h3= t('js.admin.panels.enterprise_producer.producer')
%p= t('js.admin.panels.enterprise_producer.producer_desc')
.bottom= t('js.admin.panels.enterprise_producer.producer_example')
%h3
{{ 'js.admin.panels.enterprise_producer.producer' | t }}
%p
{{ 'js.admin.panels.enterprise_producer.producer_desc' | t }}
.bottom
{{ 'js.admin.panels.enterprise_producer.producer_example' | t }}
%a.button.selector.non-producer{ ng: { click: 'enterprise.owned && changeToNonProducer()', class: "{selected: enterprise.is_primary_producer==false, disabled: !enterprise.owned}" } }
.top
%h3= t('js.admin.panels.enterprise_producer.non_producer')
%p= t('js.admin.panels.enterprise_producer.non_producer_desc')
.bottom= t('js.admin.panels.enterprise_producer.non_producer_example')
%h3
{{ 'js.admin.panels.enterprise_producer.non_producer' | t }}
%p
{{ 'js.admin.panels.enterprise_producer.non_producer_desc' | t }}
.bottom
{{ 'js.admin.panels.enterprise_producer.non_producer_example' | t }}
%a.button.update.fullwidth{ ng: { show: "enterprise.owned", class: "{disabled: saved() && !saving, saving: saving}", click: "save()" } }
%span{ ng: {hide: "saved() || saving" } }
= t('js.admin.panels.save')
{{ 'js.admin.panels.save' | t }}
%i.icon-save
%span{ ng: {show: "saved() && !saving" } }
= t('js.admin.panels.saved')
{{ 'js.admin.panels.saved' | t }}
%i.icon-ok-sign
%span{ ng: {show: "saving" } }
= t('js.admin.panels.saving')
{{ 'js.admin.panels.saving' | t }}
%i.icon-refresh

View File

@@ -2,16 +2,16 @@
.alpha.omega.sixteen.columns
%h4.status-ok.text-center{ ng: { show: "issues.length == 0 && warnings.length == 0" } }
%i.icon-ok-sign
= t('js.admin.panels.enterprise_status.status_title', name: '{{ object.name }}')
{{ 'js.admin.panels.enterprise_status.status_title' | t:{ name: object.name } }}
%table{ ng: { show: "issues.length > 0 || warnings.length > 0" } }
%thead
%th.severity
= t('js.admin.panels.enterprise_status.severity')
{{ 'js.admin.panels.enterprise_status.severity' | t }}
%th.description
= t('js.admin.panels.enterprise_status.description')
{{ 'js.admin.panels.enterprise_status.description' | t }}
%th.resolve
= t('js.admin.panels.enterprise_status.resolve')
{{ 'js.admin.panels.enterprise_status.resolve' | t }}
%tr{ ng: { repeat: "issue in issues"} }
%td.severity
%i.icon-warning-sign.issue

View File

@@ -7,7 +7,7 @@
'ng-model' => 'exchange.select_all_variants',
'ng-change' => 'setExchangeVariants(exchange, incomingExchangeVariantsFor(exchange.enterprise_id), exchange.select_all_variants)',
'id' => 'order_cycle_outgoing_exchange_{{ $parent.$index }}_select_all_variants' }
= t('admin.select_all')
{{ 'admin.select_all' | t }}
.exchange-products
-# Scope product list based on permissions the current user has to view variants in this exchange

View File

@@ -7,7 +7,7 @@
'ng-model' => 'exchange.select_all_variants',
'ng-change' => 'setExchangeVariants(exchange, suppliedVariants(exchange.enterprise_id), exchange.select_all_variants)',
'id' => 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants' }
= t('admin.select_all')
{{ 'admin.select_all' | t }}
.exchange-products
-# No need to scope product list based on permissions, because if an incoming exchange is visible,
@@ -36,7 +36,7 @@
'ofn-sync-distributions' => '{{ product.master_id }}',
'id' => 'order_cycle_incoming_exchange_{{ $parent.$index }}_variants_{{ product.master_id }}',
'ng-disabled' => '!order_cycle.editable_variants_for_incoming_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_incoming_exchanges[exchange.enterprise_id].indexOf(product.master_id) < 0' }
= t('admin.obsolete_master')
{{ 'admin.obsolete_master' | t }}
.exchange-product-variant{'ng-repeat' => 'variant in product.variants'}
%label

View File

@@ -1,6 +1,6 @@
.row.exchange-tags
.sixteen.columns.alpha.omega
%span.text-normal
= t('admin.tags')
{{ 'admin.tags' | t }}
%br
%tags-with-translation.fullwidth{ object: 'object' }

View File

@@ -0,0 +1,23 @@
#schedule-dialog
.text-normal.margin-bottom-30.text-center
%span{ ng: { hide: 'schedule.id' } }= t('admin.order_cycles.index.adding_a_new_schedule')
%span{ ng: { show: 'schedule.id' } }= t('admin.order_cycles.index.updating_a_schedule')
%form{ name: 'schedule_form', novalidate: true, ng: { submit: "submit()" }}
.text-center.margin-bottom-20
%input.fullwidth{ type: 'text', name: 'name', required: true, placeholder: t('admin.order_cycles.index.schedule_name_placeholder'), ng: { model: "schedule.name" } }
%div{ ng: { show: "submitted && schedule_form.$pristine" } }
.error{ ng: { show: "(schedule_form.name.$error.required)" } }
= t('admin.order_cycles.index.name_required_error')
.order-cycles-selector.text-center.margin-bottom-30
.text-center
%input.button{ type: 'submit', value: t('admin.order_cycles.index.create_schedule'), ng: { hide: 'schedule.id' } }
%input.button{ type: 'submit', value: t('admin.order_cycles.index.update_schedule'), ng: { show: 'schedule.id' } }
%span{ ng: { show: 'schedule.id' } } or
%input.button.red{ type: 'button', value: t('admin.order_cycles.index.delete_schedule'), ng: { show: 'schedule.id', click: 'delete()'} }
or
%input.button{ type: 'button', value: t('actions.cancel'), ng: { click: 'close()' } }

View File

@@ -3,9 +3,9 @@
{{$getDisplayText()}}
%span.tag-with-rules{ ng: { if: "data.rules == 1" } }
&mdash;
= t('admin.has_one_rule')
{{ 'admin.has_one_rule' | t }}
%span.tag-with-rules{ ng: { if: "data.rules > 1" } }
&mdash;
= t('admin.has_n_rules', { num: '{{data.rules}}' })
{{ 'admin.has_n_rules' | t:{ num: data.rules } }}
%span{ ng: { if: "!data.rules" } }
{{$getDisplayText()}}

View File

@@ -1,4 +1,5 @@
%tags-input{ template: 'admin/tag.html',
"placeholder" => t('admin.order_cycles.form.add_a_tag'),
ng: { model: 'object[tagsAttr]', class: "{'limit-reached': limitReached}"},
on: { tag: { added: 'tagAdded()', removed:'tagRemoved()' } } }
%auto-complete{ ng: { if: "findTags" }, source: "findTags({query: $query})",

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