Compare commits

..

341 Commits
v0.9 ... v1.0

Author SHA1 Message Date
Rohan Mitchell
387021929e Merge branch 'master' into rob-github-fixes 2015-06-16 15:05:01 +10:00
Rob Harrington
30af5d4278 Enterprise relatives include self where appropriate for serialized injection data 2015-06-15 19:45:29 +08:00
Rob Harrington
92082ce95c Adding filter back on producers page 2015-06-15 16:35:41 +08:00
Rob Harrington
1558ddb1eb Fixing index enterprise serializer so that payment methods issue displays when no payment methods are present 2015-06-15 16:15:06 +08:00
Rob Harrington
0038ebaa1f Fix styling issue for full sixteen column enterprise index panel 2015-06-15 16:10:33 +08:00
Rob Harrington
943c702e88 Hiding 'more' list if there are no overflow filter selectors 2015-06-15 15:54:55 +08:00
Rob Harrington
fb19feb357 Adding filters back to the hub page 2015-06-15 15:43:43 +08:00
Rob Harrington
e09431fa20 Styling tweaks 2015-06-15 15:43:19 +08:00
Rob Harrington
fb11c93943 Making ul element the root of filter_selectors directive, so resolve issue with using ng-repeat element as root of a replacement directive 2015-06-15 15:43:01 +08:00
Rob Harrington
727e8a81d6 Making sure enterprise serializer serializes no taxons as an empty array 2015-06-15 15:41:25 +08:00
Rob Harrington
0e96a23a52 Fixing filters selector directive to that an allSelector watcher isn't required for generation on selectors to work 2015-06-15 12:06:23 +08:00
Maikel Linke
80bf6e61ad redirect /t/products/:id to / 2015-06-13 11:59:52 +10:00
Maikel Linke
c6d01055d6 updating relationship spec 2015-06-12 19:32:56 +10:00
Rob Harrington
82d31b908f More styling tweaks 2015-06-12 16:09:53 +08:00
Rob Harrington
066c8876ff Only serializing unresolved enterprise issues, styling tweaks and fixes for index 2015-06-12 15:49:01 +08:00
Maikel Linke
de1971072e update relationship js spec 2015-06-12 17:09:04 +10:00
Maikel Linke
f44ac5b27b Merge branch 'url-redirects' into e2e-links 2015-06-12 17:03:31 +10:00
Maikel Linke
d717c38f6d Filter relationships by permission 2015-06-12 17:03:17 +10:00
Maikel Linke
61effc03c1 add "Enterprise Relationships" tab for non-admins 2015-06-12 17:03:17 +10:00
Maikel Linke
f2bc98e812 E2E: select all permissions 2015-06-12 17:03:17 +10:00
Rob Harrington
795b2700b4 Merge branch 'master' into enterprise-index-revamp 2015-06-12 12:47:58 +08:00
Rob Harrington
6ab5efbe02 Last minute styling adjustments 2015-06-12 12:40:24 +08:00
Rob Harrington
59d5ebe9d4 Changes to copy 2015-06-12 12:32:17 +08:00
Rob Harrington
1fb1733644 Adding link to user guide to enterprises index and dashboard 2015-06-12 12:31:57 +08:00
Rob Harrington
775718c776 Adding status panel on enterprise index 2015-06-12 12:09:00 +08:00
Rohan Mitchell
2b763271a7 Merge branch 'master' into optimise-shopfront 2015-06-12 12:15:20 +10:00
Maikel Linke
d61073f08d redirect /enterprises to / 2015-06-12 10:47:50 +10:00
Maikel Linke
2fb8f9f8a3 Redirect /products to /
GitHub issue #571
2015-06-12 10:47:50 +10:00
Rohan Mitchell
4f311543ae Merge branch 'master' into enterprise-index-revamp 2015-06-12 10:26:11 +10:00
Rob Harrington
eed27ceb31 Shipping Method feature specs work with new enteprise user enterprise index 2015-06-12 03:10:50 +08:00
Rob Harrington
77432ffc41 Payment Method feature specs work with new enteprise user enterprise index 2015-06-12 03:10:37 +08:00
Rob Harrington
5d2b36c667 Enterprise Fee feature specs work with new enteprise user enterprise index 2015-06-12 03:10:14 +08:00
Rob Harrington
61beb38e9c Bringing back delayed_job on enterprise emails - acctidentally took it out earlier 2015-06-12 03:09:40 +08:00
Rob Harrington
efca4dde10 Fixing enterprises feature spec 2015-06-12 01:49:39 +08:00
Rob Harrington
d0b7550629 Removing screenshot from spec 2015-06-12 01:49:39 +08:00
Rob Harrington
6f975593fe Splitting enterprise index feature specs into their own file, reinstating old enterprise index for super admin users 2015-06-12 01:49:39 +08:00
Rob Harrington
64ed80f845 Enterprise index action load enterprise_set for super admin 2015-06-12 01:49:39 +08:00
Rob Harrington
f80a5fe558 Fixing reference to change_type_form partial from single enterprise dashboard 2015-06-12 01:49:38 +08:00
Rob Harrington
1b52564d58 Rerouting welcome page to be an enterprise action, updates to copy for package selection 2015-06-12 01:49:38 +08:00
Rob Harrington
1cd6866879 Fixing issue with auto-creation of new contact user for enterprises caused by delayed-job 2015-06-12 01:49:37 +08:00
Rob Harrington
1c1f82f4ee Using events to update index row text on save, adding alert icons for enterprises without producer or package selected 2015-06-12 01:49:37 +08:00
Rob Harrington
95073f6fe7 Adding actual link to the manage link on enterprises index 2015-06-12 01:49:37 +08:00
Rob Harrington
e575b0e490 Switching enterprise index to its own dedicated serializer, so we can spit out ownership 2015-06-12 01:49:37 +08:00
Rob Harrington
5a08344812 Changing 'shop' column and panel to 'package' 2015-06-12 01:49:37 +08:00
Rob Harrington
e3d7c00c8e Removing option of 'producer profile only' from enterprise shop panel 2015-06-12 01:49:36 +08:00
Rob Harrington
8aa55088ab Adding a parent directive to coorindate styling of panel tabs 2015-06-12 01:49:36 +08:00
Rob Harrington
a90cd0f8e0 Owners can update sells on enterprises they own 2015-06-12 01:49:36 +08:00
Rob Harrington
6b35e993bd WIP: More work on panel content, styling and data submission logic 2015-06-12 01:49:36 +08:00
Rob Harrington
a586a52c23 Shortcutting around existing Enterprise service, so that we can use it for something more useful 2015-06-12 01:49:36 +08:00
Rob Harrington
b84f5a26a1 WIP: Splitting type panel into separate producer and shop panels, playing with styling 2015-06-12 01:49:35 +08:00
Rob Harrington
451ba1c01b panel rows adjust to span the number of visible columns 2015-06-12 01:49:35 +08:00
Rob Harrington
c441c8c6cb Columns service holds a column count and notifies rootscope when it changes 2015-06-12 01:49:35 +08:00
Rob Harrington
0c36738472 Adding basic generalised panel row infrastructure to indexUtils 2015-06-12 01:49:35 +08:00
Rob Harrington
ff3d9e27ec Upgrade angular-rails-templates 2015-06-12 01:49:35 +08:00
Rob Harrington
d5f9b40707 WIP: Basic version of revamped enterprise index 2015-06-12 01:49:34 +08:00
Rob Harrington
02d3d34826 Adding basic angular infrastructure for enterprises 2015-06-12 01:49:34 +08:00
Rob Harrington
5215623864 Adding bindonce to admin 2015-06-12 01:49:34 +08:00
Rob Harrington
ed7a53968c Using clearer json_request? method for customers controller 2015-06-12 01:49:34 +08:00
Rob Harrington
c311bcdca7 Overriding enterprises index action to use AMS for json requests, and prevent collection loading for html requests 2015-06-12 01:49:33 +08:00
Rohan Mitchell
ecbf3c8fa7 Ensure we start with consistent config settings 2015-06-11 16:16:36 +10:00
Rohan Mitchell
bfeb63c8d7 Ensure that changes to Spree::Config.products_require_tax_category do not leak out of the relevant spec 2015-06-11 14:16:18 +10:00
Rohan Mitchell
6dea3fa19d Merge branch 'fix-duplicate-fees' into combined/ginerr_bugfixes_fix-duplicate-fees 2015-06-11 12:56:32 +10:00
Rohan Mitchell
075e9edbf6 Merge branch 'ginerr_bugfixes' into combined/ginerr_bugfixes_fix-duplicate-fees 2015-06-11 12:56:27 +10:00
Maikel Linke
a8b6f2942a Releasing Assets Version 1.1
The uglifier update affects only re-compiled assets. In order to replace
the broken assets (e.g. #396) with re-compiled assets, we change the
assets version number.
2015-06-11 10:54:30 +10:00
Rohan Mitchell
604360034b Make filter method private 2015-06-10 17:04:09 +10:00
Rohan Mitchell
a0fd91dc57 Do not preload_app with unicorn, update newrelic agent so that it doesn't require this setting. 2015-06-10 17:03:56 +10:00
Rohan Mitchell
d79129880e Put lock around adjustment clear/re-create to avoid race condition resulting in duplicate fees 2015-06-10 17:02:30 +10:00
Rohan Mitchell
7412e92665 Merge branch 'master' into optimise-shopfront 2015-06-10 16:39:02 +10:00
Rohan Mitchell
ee01113fe1 Fix duplicate factory value spec error 2015-06-10 15:31:53 +10:00
Maikel Linke
5a7231579c update uglifier to 2.7.1 2015-06-10 13:58:52 +10:00
Maikel Linke
3c38c8e504 Merge branch 'adjustment-metadata-deletion' into combined/session-store_adjustment-metadata_uglifier
Conflicts:
	db/schema.rb
2015-06-10 13:56:36 +10:00
Maikel Linke
6c0238deac scoping down large request spec 2015-06-10 13:50:55 +10:00
Maikel Linke
f88f42283a Session stored in ActiveRecored instead of Cookies
The cookie store is not big enough in some cases. In order to solve a
CookieOverflow error and maybe track down the underlying issue this
patch uses the database instead of cookies to store session data.
2015-06-10 13:49:24 +10:00
Maikel Linke
88872b4b49 add spec_helper to customers_controller_spec 2015-06-06 11:49:49 +10:00
Maikel Linke
153360d17b Let the database delete adjustment metadata
GitHub issue #582

We encountered a foreign key violation on adjustment metadata even
though rails should handle that.

    Action: order.adjustments.where(originator_type: 'EnterpriseFee').destroy_all

    Adjustment: has_one :metadata, class_name: 'AdjustmentMetadata' dependent: :destroy

So we update the foreign key to cause a delete in the database.
2015-06-05 16:10:58 +10:00
Rohan Mitchell
80834a0c27 Merge branch 'master' into ginerr_bugfixes 2015-06-05 15:49:43 +10:00
Maikel Linke
d6c630dad9 add spec_helper to customers_controller_spec 2015-06-05 14:25:45 +10:00
Maikel Linke
7461009c3b Merge branch 'handle-invalid-referer-urls' into combined/xero-report_analytics-bugfixes 2015-06-05 14:23:58 +10:00
Maikel Linke
252e9be016 Merge branch 'remove-old-bugsnag-notification' into combined/xero-report_analytics-bugfixes 2015-06-05 14:23:03 +10:00
Maikel Linke
f324471495 Merge branch 'index_enterprise_permalink' into combined/xero-report_analytics-bugfixes 2015-06-05 14:20:13 +10:00
Maikel Linke
f438a44f26 Merge remote-tracking branch 'origin/analytics' into combined/xero-report_analytics-bugfixes
Conflicts:
	app/controllers/spree/admin/orders_controller_decorator.rb
2015-06-05 14:19:54 +10:00
Maikel Linke
1b91082c1c Merge branch 'show-order-without-current-distributor' into combined/xero-report_show-order-without-distributor 2015-06-05 13:48:47 +10:00
Maikel Linke
ffa960b02e Merge remote-tracking branch 'origin/xero-report' into combined/xero-report_show-order-without-distributor 2015-06-05 13:48:24 +10:00
Maikel Linke
41dafce0db Remove obsolete Bugsnag notification 2015-06-05 13:46:15 +10:00
Maikel Linke
e35b39c7cf Handle invalid referer URLs
Rescues URI::InvalidURIError of URL(request.referer).
2015-06-05 12:43:49 +10:00
Maikel Linke
552bbf221c Delete obsolete paragraph in registration #595 2015-06-05 11:01:40 +10:00
Rohan Mitchell
f09fad464e Merge branch 'master' into optimise-shopfront 2015-06-05 07:28:05 +10:00
Rohan Mitchell
fc7e33d706 Fall back on individual calculations when pre-prepared values are not present 2015-06-04 16:43:19 +10:00
Rohan Mitchell
ef3155a16a Pull product listing fee calculations out of serializer loop 2015-06-04 16:27:32 +10:00
Rohan Mitchell
3846d16822 Add methods to load fees for a number of variants in one go 2015-06-04 16:22:06 +10:00
Continuous Integration
6051c81959 Auto-merge from CI [skip ci] 2015-06-04 15:39:43 +10:00
Rohan Mitchell
486c2f9b42 WIP: Skip EnterpriseFeeApplicator step when computing fees 2015-06-04 12:13:04 +10:00
Rohan Mitchell
27bc28ffa4 Index variants by id 2015-06-04 12:09:34 +10:00
Rohan Mitchell
cf0031d9a5 WIP: Optimise enterprise fee calculation 2015-06-04 11:53:09 +10:00
Rohan Mitchell
85d1d67dac Sort orders as required by spec, fixes intermittent fail 2015-06-04 09:43:36 +10:00
Continuous Integration
a1425c5e07 Auto-merge from CI [skip ci] 2015-06-04 07:22:43 +10:00
Maikel Linke
5d77a48ef3 Merge branch 'master' of github.com:openfoodfoundation/openfoodnetwork into show-order-without-current-distributor 2015-06-03 20:36:12 +10:00
Rob Harrington
e93736b123 Ordering managed orders by id to fix spec 2015-06-03 18:16:07 +08:00
Maikel Linke
aea6277b77 Merge branch 'master' of github.com:openfoodfoundation/openfoodnetwork into index_enterprise_permalink 2015-06-03 19:54:29 +10:00
Rob Harrington
3855ae1337 Fixing bug on OC interface that prevented hubs from pulling their own products through 2015-06-03 16:18:44 +08:00
Rob Harrington
359328a96e Producers and distributors lists include self where appropriate 2015-06-03 16:18:44 +08:00
Rob Harrington
dbd81e60a1 Fixing customer index feature spec, only checking shop when something has been selected 2015-06-03 16:18:09 +08:00
Rob Harrington
7c9b4dbc3e Resolving unmerged section in bulk order management template 2015-06-03 15:33:04 +08:00
Rob Harrington
09160c8ea6 Fixing customers controller spec 2015-06-03 15:23:55 +08:00
Rob Harrington
439d122e93 Merge branch 'master' into customers
Conflicts:
	app/assets/javascripts/admin/bulk_order_management.js.coffee
	app/assets/javascripts/admin/bulk_product_update.js.coffee
	app/assets/javascripts/admin/directives/line_item_upd_attr.js.coffee
	app/views/spree/admin/orders/bulk_management.html.haml
	db/schema.rb
	spec/javascripts/unit/bulk_order_management_spec.js.coffee
2015-06-03 15:19:40 +08:00
Rohan Mitchell
f1019e9221 Upgrade unicorn 2015-06-03 16:53:46 +10:00
Rohan Mitchell
2c0da5e350 Output parallel spec runtime log -> evenly split spec grouping 2015-06-03 16:38:47 +10:00
Maikel Linke
d2a61dc096 Merge branch 'master' of github.com:openfoodfoundation/openfoodnetwork into registration-wizard-text 2015-06-03 16:37:25 +10:00
Rohan Mitchell
0569ef0505 Only record analytics in production. Also record them in admin backend. 2015-06-03 16:36:31 +10:00
Rohan Mitchell
17d123db63 ng-cloak producers page 2015-06-03 16:28:43 +10:00
Rohan Mitchell
4d789b70ed Merge branch 'products-and-inventory-report' into combined/bulk-product-edit-and-ng-cloak 2015-06-03 15:12:29 +10:00
Maikel Linke
7302963605 inventory report: filter was broken because filter_to_order_cycle returned nil
[skip ci]
2015-06-03 15:11:32 +10:00
Rohan Mitchell
ad4e17b77a Merge branch 'master' into combined/bulk-product-edit-and-ng-cloak 2015-06-03 15:10:12 +10:00
Rohan Mitchell
cd8084ae3f Merge branch 'master' into parallel-tests
Conflicts:
	script/ci/run_tests.sh
2015-06-03 15:08:15 +10:00
Rohan Mitchell
41b348f594 Merge branch 'master' into combined/bulk-product-edit-and-ng-cloak 2015-06-03 15:05:51 +10:00
Rohan Mitchell
2b3689fd93 Run CI specs in parallel 2015-06-03 14:29:38 +10:00
Rohan Mitchell
db47c01784 Initial config for parallel spec running 2015-06-03 14:29:38 +10:00
Rohan Mitchell
769a04d2e0 Merge branch 'master' into optimise-shopfront 2015-06-03 13:02:58 +10:00
Rohan Mitchell
36dc0d5ccd Do not run performance specs in CI 2015-06-03 13:00:07 +10:00
Rohan Mitchell
b3878b126b Decouple generic injection spec from EnterpriseSerializer 2015-06-03 12:53:46 +10:00
Rohan Mitchell
c6f6c11a43 Add wait between clicks to fix race condition 2015-06-03 12:51:15 +10:00
Rohan Mitchell
473322c7e6 CI: Add more robust merge-to-master script 2015-06-03 12:25:28 +10:00
Rohan Mitchell
8afffdae9a Fix error when product does not have a master variant 2015-06-03 12:13:42 +10:00
Maikel Linke
4b6222bbe2 Updating spec using new button label 2015-06-03 12:08:47 +10:00
Maikel Linke
96177b7cd7 Add unique index to enterprise permalink 2015-06-03 11:57:22 +10:00
Maikel Linke
cb2adea59f Remove executable bit from a migration file 2015-06-03 10:16:29 +10:00
Rohan Mitchell
22230294ab Merge branch 'master' into optimise-shopfront 2015-06-03 10:07:42 +10:00
Maikel Linke
2853885f26 Merge branch 'master' of github.com:openfoodfoundation/openfoodnetwork into registration-wizard-text 2015-06-03 09:47:37 +10:00
Rohan Mitchell
a22da1ae51 Merge branch 'ng-cloak' into combined/bulk-product-edit-and-ng-cloak 2015-05-29 16:54:01 +10:00
Maikel Linke
159b33e2db Merge branch 'master' of github.com:openfoodfoundation/openfoodnetwork into bulk-product-edit 2015-05-29 16:52:18 +10:00
Maikel Linke
0d3cdb9c69 Expand All button to show all variants in BPE 2015-05-29 16:51:55 +10:00
Rohan Mitchell
5c3a59acab ng-cloak order cycles selector, tabs and shopfront 2015-05-29 16:39:41 +10:00
Rohan Mitchell
50ae331d94 ng-cloak mobile menu 2015-05-29 16:03:16 +10:00
Maikel Linke
fe27b1d446 text changes to the registration wizard 2015-05-29 15:24:17 +10:00
Maikel Linke
bf935623dc changing default mailer url in development from test.com to 0.0.0.0:3000 2015-05-29 15:24:17 +10:00
Maikel Linke
678b591c18 Explain how to disable delayed jobs to send emails again 2015-05-29 15:24:16 +10:00
Maikel Linke
503b687ed1 Display distributor banner only if current_distributor is present 2015-05-29 15:19:05 +10:00
Rohan Mitchell
952353da8c Merge branch 'bulk-product-edit' into combined/single-order-patches-and-bulk-product-edit
Conflicts:
	spec/features/admin/bulk_product_update_spec.rb
2015-05-29 15:08:30 +10:00
Rohan Mitchell
e5b3736e86 Merge branch 'single-order-patches' into combined/single-order-patches-and-bulk-product-edit 2015-05-29 14:36:51 +10:00
Continuous Integration
c14de4e97f Auto-merge from CI [skip ci] 2015-05-29 14:29:23 +10:00
Rohan Mitchell
d478cc1f69 Serialize taxons and relatives in expected format 2015-05-29 14:03:44 +10:00
Continuous Integration
dccc9fb479 Auto-merge from CI [skip ci] 2015-05-29 12:44:44 +10:00
Rohan Mitchell
3f4f8afacd EnterpriseRelationship.relatives does not show duplicates 2015-05-29 12:19:38 +10:00
Rohan Mitchell
69c54e1d70 Only load activated relatives for EnterpriseInjectionData 2015-05-29 12:08:21 +10:00
Rohan Mitchell
cdbf02ca20 EnterpriseRelationship.relatives can find activated enterprises only 2015-05-29 12:07:43 +10:00
Rohan Mitchell
4ce9ea05f0 Merge branch 'master' into require_standard_variant 2015-05-29 10:12:14 +10:00
Rohan Mitchell
835b56b222 Attempt to fix intermittent failures in spec/features/consumer/authentication_spec.rb 2015-05-29 09:44:57 +10:00
Rohan Mitchell
7486daa2a3 Merge branch 'master' into require_standard_variant
Conflicts:
	spec/controllers/spree/admin/variants_controller_spec.rb
	spec/lib/open_food_network/permissions_spec.rb
	spec/lib/open_food_network/products_and_inventory_report_spec.rb
	spec/models/enterprise_spec.rb
2015-05-28 15:08:13 +10:00
Maikel Linke
bf9addfa42 Merge branch 'group-custom-url' into group-pages 2015-05-28 13:27:48 +10:00
Maikel Linke
ff2eed7760 Using permalink in URLs pointing to groups 2015-05-28 11:27:40 +10:00
Maikel Linke
e4f93863fd Finding unique permalink before validation. 2015-05-28 11:27:40 +10:00
Maikel Linke
aef128f2c9 permalink editable 2015-05-28 11:27:40 +10:00
Maikel Linke
19448a182e Add permalink field to enterprise groups 2015-05-28 11:27:39 +10:00
Continuous Integration
a01a53caea Auto-merge from CI [skip ci] 2015-05-28 11:05:07 +10:00
Rohan Mitchell
7f43dbf9bb Fix further intermittent failures in permissions spec 2015-05-28 10:58:12 +10:00
Rohan Mitchell
97e49c2bdb Replace 'array.sort.should == expected.sort' pattern with match_array 2015-05-28 10:46:08 +10:00
Rohan Mitchell
ccf1e2951c Fix intermittent failure in permissions spec 2015-05-28 10:45:47 +10:00
Rohan Mitchell
3ab7df88e6 Allow serialization of nil enterprise 2015-05-27 16:32:15 +10:00
Rohan Mitchell
75f1f673ad Update spec for EnterpriseSerializer 2015-05-27 16:26:31 +10:00
Rohan Mitchell
e74390a013 Remove controller specs for @active_distributors, now set via helper 2015-05-27 16:26:08 +10:00
Rohan Mitchell
41bc67e2d8 Add benchmark for product serialisation 2015-05-27 15:44:02 +10:00
Rohan Mitchell
e1b4c3b1e4 Add benchmarking test for inject_enterprises 2015-05-27 15:44:02 +10:00
Rohan Mitchell
31b726613d Avoid loading enterprise injection data when it's not be needed due to caching 2015-05-27 15:44:01 +10:00
Rohan Mitchell
dd761719ee Fix undefined Api::IdSerializer error 2015-05-27 15:44:01 +10:00
Rohan Mitchell
1a887df412 Pull taxon computation out of the serialization loop 2015-05-27 15:44:01 +10:00
Rohan Mitchell
2c92b5a751 Find all supplied and distributed taxons 2015-05-27 15:44:01 +10:00
Rohan Mitchell
3afd636577 Pull relatives computation out of the serialization loop 2015-05-27 15:44:01 +10:00
Rohan Mitchell
cf79b90044 Load relatives of all enterprises in one go 2015-05-27 15:44:01 +10:00
Rohan Mitchell
4a59c85b3e Inject current hub from AMS rather than RABL 2015-05-27 15:44:01 +10:00
Rohan Mitchell
704955a185 Load active distributors where they're needed rather than in most controllers 2015-05-27 15:44:01 +10:00
Rohan Mitchell
ee8db23fd9 Pull shipping method service computations out of the serialization loop 2015-05-27 15:44:01 +10:00
Rohan Mitchell
f0e909c92b Look up the shipping services (pickup, delivery) that different hubs provide 2015-05-27 15:44:01 +10:00
Rohan Mitchell
f940984ca3 Pull earliest closing time computations out of the serialization loop 2015-05-27 15:44:01 +10:00
Rohan Mitchell
769edbe9d5 Find the earliest closing times for each distributor in an active order cycle 2015-05-27 15:44:01 +10:00
Rohan Mitchell
c5f00d87bd When loading products for shopfront, load all master variants in one go 2015-05-27 15:44:01 +10:00
Rohan Mitchell
99cb09c6f7 When loading products for shopfront, load all variants in one go 2015-05-27 15:44:01 +10:00
Continuous Integration
5377af9cf9 Auto-merge from CI [skip ci] 2015-05-24 09:52:53 +10:00
Rick Giner
a5482c269f #541 Fixed issue of showing negative 'more' numbers, and only working for current Hub 2015-05-24 09:52:34 +10:00
Maikel Linke
5a43ed2046 Merge branch 'master' of github.com:openfoodfoundation/openfoodnetwork into bulk-product-edit 2015-05-22 18:17:20 +10:00
Maikel Linke
28dae3c6c6 Enterprises cannot add themselves to Groups 2015-05-22 15:23:59 +10:00
Rob Harrington
5d47dc2fdb Sort array so that order doesn't cause spec fail 2015-05-22 15:03:21 +10:00
Rob Harrington
5b65f67737 Amending spec expect after_create when we want after_save 2015-05-22 15:02:49 +10:00
Rob Harrington
e931f4b31f Merge branch 'master' into require_standard_variant 2015-05-22 12:22:54 +10:00
Rob Harrington
63f3ede766 Prepare master variants for duplication as standard variant by ensuring they have a unit value and that the product has a variant unit 2015-05-22 12:22:05 +10:00
Rob Harrington
d43df86201 Moving conditional logic into ensure_standard_variant 2015-05-22 12:20:31 +10:00
Maikel Linke
9c137ccf0f provide tax_categories in spec 2015-05-22 11:03:21 +10:00
Maikel Linke
7e4751cb3a updating bulk product js spec 2015-05-21 22:30:23 +10:00
Maikel Linke
e6b6303f5e Merge branch 'master' of github.com:openfoodfoundation/openfoodnetwork into bulk-product-edit 2015-05-21 18:03:11 +10:00
Maikel Linke
9c884b31a3 Merge branch 'master' of github.com:openfoodfoundation/openfoodnetwork into single-order-patches 2015-05-21 18:01:16 +10:00
Maikel Linke
f017197221 orders list: filter by distributor and order cycle 2015-05-21 18:00:14 +10:00
Rob Harrington
cd44d43b3e Adding price to line_item serializer (oops, forgot to include when merging in master) 2015-05-21 17:48:35 +10:00
Rob Harrington
903ed7e507 Merge branch 'master' into variable_weights
Conflicts:
	app/assets/javascripts/admin/bulk_order_management.js.coffee
	app/views/spree/admin/orders/bulk_management.html.haml
	app/views/spree/api/line_items/bulk_show.v1.rabl
	spec/features/admin/bulk_order_management_spec.rb
2015-05-21 17:31:33 +10:00
Rob Harrington
79a59e2e81 Add order_with_distributor factory 2015-05-21 13:34:32 +10:00
Maikel Linke
73884d4f01 BPE: Display notice about variant overrides 2015-05-21 13:01:28 +10:00
Maikel Linke
2ed519ef50 on_demand checkbox for variants 2015-05-21 12:37:10 +10:00
Maikel Linke
1936767084 BPE: new col for tax category 2015-05-21 11:06:08 +10:00
Rob Harrington
0b28771364 Removing unrequired specs for variant/product 'units_show' 2015-05-20 21:06:20 +10:00
Rob Harrington
1aca4657d9 Oops, switch managed_products to editable_products for Api::ProductsController 2015-05-20 20:59:06 +10:00
Rob Harrington
3431c687b8 Making sure every created by factories has a distributor 2015-05-20 20:54:27 +10:00
Rob Harrington
65a6329132 Products and inventory reports scopes products to visible in permissions 2015-05-20 16:19:08 +10:00
Rob Harrington
8132f07d88 Adding visible products method to permissions 2015-05-20 15:53:10 +10:00
Maikel Linke
1e26466d11 bulk product edit: "on demand" for new product 2015-05-20 15:29:35 +10:00
Maikel Linke
6953f61939 bulk product edit: new col "on demand" 2015-05-20 15:07:22 +10:00
Rob Harrington
01d4cf6ecf Renaming managed_products permissions method to editable_products 2015-05-20 15:02:36 +10:00
Rob Harrington
05131de1ad Use full_name on BOM instead of options_text 2015-05-20 14:11:31 +10:00
Maikel Linke
0a0bb67277 No SKU for cloned products. Community topic 175 2015-05-20 14:05:14 +10:00
Rob Harrington
8d73b2f532 involving... order cycle scopes return distinct OCs 2015-05-20 13:47:01 +10:00
Rob Harrington
c56efabfbe Removing obsolete rabl templates 2015-05-20 11:52:49 +10:00
Rob Harrington
0ad2978926 Removing old managed route from api orders controller and switching BOM over to use new controller action 2015-05-20 11:48:48 +10:00
Rob Harrington
fc55a000b8 Adding managed controller action which uses new order serializer to render json 2015-05-20 11:48:13 +10:00
Rob Harrington
823adf3272 Translating existing order-related rabl templates accross to AMS 2015-05-20 11:45:48 +10:00
Rob Harrington
7f80c02c0e Adding route for managed route for admin orders 2015-05-20 11:45:05 +10:00
Maikel Linke
828456118b Remove forgotten binding.pry 2015-05-20 11:15:18 +10:00
Maikel Linke
fa87c53777 Merge branch 'master' of github.com:openfoodfoundation/openfoodnetwork into group-pages 2015-05-20 10:22:28 +10:00
Maikel Linke
6b956a8a38 Updating product clone spec 2015-05-20 10:19:37 +10:00
Maikel Linke
0c46f963ce Merge branch 'master' of github.com:openfoodfoundation/openfoodnetwork into bulk-product-edit 2015-05-20 10:19:03 +10:00
Rohan Mitchell
f1899a7558 Merge branch 'master' into xero-report 2015-05-15 16:57:11 +10:00
Rohan Mitchell
70b5ac4785 Add column for whether the order has been paid for 2015-05-15 16:55:52 +10:00
Rohan Mitchell
f7642b2a1b When blank values are submitted, do not override defaults 2015-05-15 16:51:04 +10:00
Rohan Mitchell
a467d3c379 Add filtering to xero invoices report - order date range, hub and order cycle 2015-05-15 16:20:56 +10:00
Rohan Mitchell
3d4a0f8407 Xero invoices report: Preserve form fields on submit, do not show rows with no cost 2015-05-15 15:27:46 +10:00
Rohan Mitchell
3640a71ab8 Reorder methods 2015-05-15 15:05:18 +10:00
Rohan Mitchell
ca37efdd26 Display whether there is tax included in shipping 2015-05-15 12:44:48 +10:00
Rohan Mitchell
dc8270ed72 Display amounts on xero invoice report 2015-05-15 12:35:20 +10:00
Rohan Mitchell
0dcd8eb8cc Find adjustments with and without tax 2015-05-15 12:35:19 +10:00
Rohan Mitchell
ca1d88d8b1 Find line items with and without tax 2015-05-15 12:35:19 +10:00
Rohan Mitchell
5660e3737e Extract order rows generation to method 2015-05-15 12:35:19 +10:00
Rohan Mitchell
c5b618b1f4 Admin can customise some fields on Xero invoices report
Add require for xero invoices report spec
2015-05-15 12:35:14 +10:00
Rohan Mitchell
0737ac8da0 Write an rspec table matcher that gives informative error messages 2015-05-15 12:35:14 +10:00
Rohan Mitchell
0a2f2e0fba Output summary data without customisation
Add route for xero invoices report

Add require for reports controller decorator
2015-05-15 12:35:05 +10:00
Rohan Mitchell
38e1bd4139 Fix indentation 2015-05-15 12:17:16 +10:00
Rob Harrington
c8502747be Fixing layout of customers index 2015-05-14 12:37:55 +10:00
Rob Harrington
78fc3e376b Fixing styling of inputs for with pending/success/error status 2015-05-14 11:39:37 +10:00
Rob Harrington
50d0d04994 Removing obsolete dataSubmitter service 2015-05-14 11:38:55 +10:00
Rob Harrington
640c02570d Splitting out specs for switchClass service 2015-05-13 16:41:28 +10:00
Rob Harrington
3849b39d3e Splitting out specs for pending changes service 2015-05-13 16:39:43 +10:00
Rob Harrington
ffac0e4ceb Adding ngTagsInput to angular spec manifest 2015-05-13 16:06:38 +10:00
Rob Harrington
a473d0ed11 Checking in db version change 2015-05-13 15:58:03 +10:00
Rob Harrington
34f5cfb6b5 Completed orders require a customer, add association logic 2015-05-13 12:44:38 +10:00
Rob Harrington
1559b4e30a Adding customer reference to orders 2015-05-13 12:44:37 +10:00
Rob Harrington
ed941e211d Don't require a code on customer 2015-05-13 12:44:37 +10:00
Rob Harrington
dd9c192d48 Shuffling layout a little on customer index 2015-05-13 12:44:37 +10:00
Rob Harrington
b364994cc8 Adding tags input to customer index using ngTagsInput 2015-05-13 12:44:37 +10:00
Rob Harrington
3bc69242ce Style tweaks 2015-05-13 12:44:37 +10:00
Rob Harrington
d2e8b23dd4 Creating association between enterprise and customers 2015-05-13 12:44:37 +10:00
Rob Harrington
5b3c9842e4 Adding acts_as_taggable to customer model 2015-05-13 12:44:36 +10:00
Rob Harrington
a03c7a5f22 Adding ngTagsInput to admin assets 2015-05-13 12:44:36 +10:00
Rob Harrington
a60fd3d388 Installing ngTagInput 2015-05-13 12:44:36 +10:00
Rob Harrington
4c5e75c3f9 Adding acts-as-taggable-on gem 2015-05-13 12:44:36 +10:00
Rob Harrington
5b49e64bf2 Hiding bulk checkboxes on customer interface (for now) 2015-05-13 12:44:36 +10:00
Rob Harrington
9add073b17 User can update customer code from customer index page 2015-05-13 12:44:36 +10:00
Rob Harrington
734ad21e82 Customers controller responds with json 2015-05-13 12:44:35 +10:00
Rob Harrington
dcde2d88ad Adding Customer resource to resources service 2015-05-13 12:44:35 +10:00
Rob Harrington
4545e0ff95 Adding request defaults to index utils module 2015-05-13 12:44:35 +10:00
Rob Harrington
3890ba9a11 Wrapping pending changes service in a class 2015-05-13 12:44:35 +10:00
Rob Harrington
8f94390363 Moving a bunch of index related services from general admin module into indexUtils 2015-05-13 12:44:35 +10:00
Rob Harrington
a873278881 Moving line-item-upd-attr to indexUtils module, renaming to obj-for-update 2015-05-13 12:44:35 +10:00
Rob Harrington
2afd501af3 Wiring up update action for customers controller 2015-05-13 12:44:34 +10:00
Rob Harrington
8f35ccf007 Adding quick search and column dropdown to customers index 2015-05-13 12:44:34 +10:00
Rob Harrington
79d50a64ae BPE uses columns controller from intex utils 2015-05-13 12:44:34 +10:00
Rob Harrington
3e7d331892 BOM uses columns controller from index utils module 2015-05-13 12:44:34 +10:00
Rob Harrington
3b7ab086c9 Fix module name 2015-05-13 12:44:34 +10:00
Rob Harrington
69ba8540c1 Moving toggle_column directive to index_utils 2015-05-13 12:44:33 +10:00
Rob Harrington
5bd842fe1a Moving toggle_column directive to dropdown module 2015-05-13 12:44:33 +10:00
Rob Harrington
f5c0ae0f41 Moving dropdown to its own module folder and renaming 2015-05-13 12:44:33 +10:00
Rob Harrington
1c03e27686 Moving dropdown to its own folder 2015-05-13 12:44:33 +10:00
Rob Harrington
7a4f0e214c Adding customers index view 2015-05-13 12:44:33 +10:00
Rob Harrington
307302038a Adding customers controller, service and resource 2015-05-13 12:44:33 +10:00
Rob Harrington
c00c93816c Renaming spec file 2015-05-13 12:44:32 +10:00
Rob Harrington
b3d314cfdb Adding require line for index_utils module to all.js 2015-05-13 12:44:32 +10:00
Rob Harrington
b6d63d40c6 Pulling columns logic out into its own services/controller in a new indexUtils module 2015-05-13 12:44:32 +10:00
Rob Harrington
220f42fcf2 Customers controller serializes data for json requests, just renders view without data for html 2015-05-13 12:44:32 +10:00
Rob Harrington
37ff61d663 Adding basic routing to display customer index page 2015-05-13 12:44:32 +10:00
Rob Harrington
57dbc33a7b Adding resource service to determine submission request based on object type 2015-05-13 12:44:31 +10:00
Rob Harrington
b16fa9cdc1 Generalising datasubmitter pendingChanges and watcher directive 2015-05-13 12:44:31 +10:00
Rob Harrington
30bb948d35 Making ofn-line-item-upd-attr work without ng-model
Conflicts:
	app/assets/javascripts/admin/directives/line_item_upd_attr.js.coffee
	app/views/spree/admin/orders/bulk_management.html.haml
2015-05-13 12:44:31 +10:00
Rick Giner
e801d6199a Passing in $event in other views that call toggle() 2015-05-11 20:33:35 +10:00
Rick Giner
62ae38372e #541 add "show more" link to producers lists in hub on home page 2015-05-11 20:31:24 +10:00
Rick Giner
b7c1a43125 Issue #540 Fix up hub list navigation 2015-05-10 18:13:30 +10:00
Rick Giner
98c1a95bd1 Issue #531 remove Google map road markers 2015-05-10 16:51:56 +10:00
Rick Giner
9c3ec950fc Revert "ginerr_#531_remove Google map road markers"
This reverts commit 3e2117134f.
2015-05-10 16:50:58 +10:00
Rick Giner
3e2117134f ginerr_#531_remove Google map road markers 2015-05-10 16:50:00 +10:00
Lynne
90dd1ea4a2 Merge pull request #1 from openfoodfoundation/variable_weights
Merging
2015-05-09 19:25:30 +01:00
Lynne Davis
26ee5c49b2 Fixing merge conflicts 2015-05-09 19:14:50 +01:00
Lynne Davis
3179887842 Do not allow line_item.unit_value to be updated if the variant.unit_value is zero 2015-05-09 19:12:24 +01:00
Lynne Davis
4d025ee7a9 Updating the spec based on @Robs suggestions, hoping for his insights. Still doesn't work. 2015-05-09 19:10:55 +01:00
Lynne Davis
521834bd76 Populate the line item unit value, when line_item created and update old data in migration 2015-05-09 19:10:55 +01:00
Lynne Davis
662c7fe368 Removing notes to myself from this file 2015-05-09 19:10:55 +01:00
Lynne Davis
54da7ae241 Adding additional logic for if the line_item unit_value is nil 2015-05-09 19:10:55 +01:00
Lynne Davis
2a991ad130 Variable Weights: Adding ability to update the weight/volume of a line_item after checkout. The price of the line_item is automatically updated to reflect the value of the new weight. 2015-05-09 19:10:55 +01:00
Lynne Davis
2f463474fb Adding specs for variable weight adjustment via builk order management 2015-05-09 19:10:55 +01:00
Lynne Davis
f7ade48e86 Update DB schema to store updatable weight on items sold 2015-05-09 19:10:55 +01:00
Continuous Integration
df14c10608 Auto-merge from CI [skip ci] 2015-05-08 13:45:56 +10:00
Rohan Mitchell
1531c476e3 Merge branch 'master' into require_standard_variant
Conflicts:
	spec/controllers/spree/admin/variants_controller_spec.rb
2015-05-08 13:45:31 +10:00
Maikel Linke
2edf5aeccd Merge branch 'master' of github.com:openfoodfoundation/openfoodnetwork into bulk-product-edit 2015-05-01 15:05:14 +10:00
Maikel Linke
993183f2f5 updating js spec: cloning product calls insertProductAfter now 2015-05-01 15:04:12 +10:00
Maikel Linke
baabb5c07f fixing BPE feature spec 2015-05-01 11:30:26 +10:00
Maikel Linke
66f847f673 showing save button at the bottom as well 2015-04-30 17:22:54 +10:00
Maikel Linke
295da25dd2 insert clone after cloned product 2015-04-30 17:17:28 +10:00
Rob Harrington
992fb2347d Merging master branch into require_standard_variant 2015-04-29 14:30:49 +10:00
Rob Harrington
a253b88525 Fixing line item controller spec 2015-04-29 10:42:38 +10:00
Lynne Davis
d344c3dec8 Updating the spec based on @Robs suggestions, hoping for his insights. Still doesn't work. 2015-04-24 16:22:17 +01:00
Lynne Davis
6045283549 Populate the line item unit value, when line_item created and update old data in migration 2015-04-24 16:17:00 +01:00
Lynne Davis
162a565140 Removing notes to myself from this file 2015-04-24 16:14:24 +01:00
Rob Harrington
ad2df56bf1 Merge branch 'require_standard_variant' of github.com:openfoodfoundation/openfoodnetwork into require_standard_variant 2015-04-24 12:19:27 +10:00
Rob Harrington
ed7b763ecf UnitsCtrl can interpret unit_value_with_description without a separating space 2015-04-24 12:15:35 +10:00
Rob Harrington
05c350b5ff Refactoring unitsCtrl 2015-04-24 11:27:47 +10:00
Rob Harrington
57be445bd4 Merge branch 'master' into require_standard_variant 2015-04-23 14:18:11 +10:00
Rohan Mitchell
f70bfee481 Merge branch 'master' into require_standard_variant 2015-04-23 09:56:41 +10:00
Rob Harrington
76d6345ab5 Merge remote-tracking branch 'origin/master' into require_standard_variant 2015-04-22 21:02:47 +10:00
Rob Harrington
699a28e14c Merge branch 'master' into require_standard_variant 2015-04-22 10:58:43 +10:00
Rob Harrington
a75a76840d Merging master into require_standard_variant 2015-04-17 21:18:24 +10:00
Rob Harrington
ff2e6d9ca4 Test deletion rather than destruction on variant model spec 2015-04-17 17:25:13 +10:00
Maikel Linke
893b743973 tidy (rm comment) 2015-04-17 17:00:18 +10:00
Maikel Linke
03fd148f41 showing profile modals on groups/hubs 2015-04-17 16:58:49 +10:00
Rob Harrington
72d553ef0c Test actual deletion of variants 2015-04-17 16:51:02 +10:00
Rob Harrington
63353ebace Don't try and delete the only variant, that will never work! 2015-04-17 16:49:14 +10:00
Rob Harrington
b9f19d5777 Fixing broken specs 2015-04-17 13:00:20 +10:00
Rob Harrington
9ee25c4e42 Making spec better 2015-04-17 11:25:18 +10:00
Rob Harrington
2d7fb3fd67 Updating name of spec 2015-04-17 11:25:18 +10:00
Rob Harrington
7596270154 A few more changes to tidy up standard variant migration 2015-04-17 11:25:18 +10:00
Rob Harrington
5d9e861ee4 Working migration to complete deprecation of master variants 2015-04-17 11:25:18 +10:00
Rob Harrington
447a5481a3 WIP: Building migration to duplicate master variants 2015-04-17 11:25:18 +10:00
Rob Harrington
8248e382f3 Greying out disabled action button 2015-04-17 11:25:18 +10:00
Rob Harrington
4b182f9248 Can't delete final variant on a product from BPE 2015-04-17 11:25:18 +10:00
Rob Harrington
2b47c9145a Cannot delete last variant of product 2015-04-17 11:25:17 +10:00
Rob Harrington
fcb3bc894b Cleanup 2015-04-17 11:25:17 +10:00
Rob Harrington
a223a2d662 Cannot remove all variants from a product 2015-04-17 11:25:17 +10:00
Rob Harrington
5e2fe56c22 Cleanup 2015-04-17 11:25:17 +10:00
Rob Harrington
89afbc80a6 Set initial on_hand to 0 2015-04-17 11:25:17 +10:00
Rob Harrington
971723964e Update outdated spec 2015-04-17 11:25:17 +10:00
Rob Harrington
28486f9e76 Only adds standard variant on create 2015-04-17 11:25:17 +10:00
Rob Harrington
869551a17c Adding a standard variant again 2015-04-17 11:25:17 +10:00
Rob Harrington
13a910c372 Replace validates_associated on master with current spree method for error reporting master saves 2015-04-17 11:25:17 +10:00
Rob Harrington
0a7b01ff07 Product requires variant_unit and master requires unit_value and/or unit_desc 2015-04-17 11:25:16 +10:00
Rob Harrington
dfb513cce7 Use after_create callback to duplicate master variant 2015-04-17 11:25:16 +10:00
Rob Harrington
3f01a459ac Adding a standard variant upon initialisation of a new instance of Spree::Product 2015-04-17 11:25:16 +10:00
Lynne Davis
83981fbb15 Adding additional logic for if the line_item unit_value is nil 2015-04-14 17:29:56 +01:00
Lynne Davis
ff935af18b Variable Weights: Adding ability to update the weight/volume of a line_item after checkout. The price of the line_item is automatically updated to reflect the value of the new weight. 2015-04-04 19:20:56 +01:00
Lynne Davis
ffd850c761 Adding specs for variable weight adjustment via builk order management 2015-04-04 19:20:41 +01:00
Lynne Davis
bf44a1c862 Update DB schema to store updatable weight on items sold 2015-04-04 19:20:27 +01:00
316 changed files with 5896 additions and 2216 deletions

4
.rspec_parallel Normal file
View File

@@ -0,0 +1,4 @@
--format progress
--format ParallelTests::RSpec::SummaryLogger --out tmp/spec_summary.log
--format ParallelTests::RSpec::RuntimeLogger --out tmp/parallel_runtime_rspec.log
--tag ~performance

View File

@@ -49,6 +49,7 @@ gem 'custom_error_message', :github => 'jeremydurham/custom-err-msg'
gem 'angularjs-file-upload-rails', '~> 1.1.0'
gem 'roadie-rails', '~> 1.0.3'
gem 'figaro'
gem 'acts-as-taggable-on', '~> 3.4'
gem 'foreigner'
gem 'immigrant'
@@ -69,7 +70,7 @@ group :assets do
gem 'turbo-sprockets-rails3'
gem 'foundation-icons-sass-rails'
gem 'momentjs-rails'
gem 'angular-rails-templates'
gem 'angular-rails-templates', '~> 0.2.0'
end
gem "foundation-rails"
gem 'foundation_rails_helper', github: 'willrjmarshall/foundation_rails_helper', branch: "rails3"
@@ -112,4 +113,5 @@ group :development do
gem 'guard-rails'
gem 'guard-zeus'
gem 'guard-rspec'
gem 'parallel_tests'
end

View File

@@ -142,12 +142,14 @@ GEM
activesupport (3.2.21)
i18n (~> 0.6, >= 0.6.4)
multi_json (~> 1.0)
acts-as-taggable-on (3.5.0)
activerecord (>= 3.2, < 5)
acts_as_list (0.1.4)
addressable (2.3.3)
andand (1.3.3)
angular-rails-templates (0.1.1)
angular-rails-templates (0.2.0)
railties (>= 3.1)
sprockets
sprockets (~> 2)
tilt
angularjs-file-upload-rails (1.1.0)
angularjs-rails (1.2.13)
@@ -249,8 +251,7 @@ GEM
erubis (2.7.0)
eventmachine (1.0.3)
excon (0.25.3)
execjs (1.4.0)
multi_json (~> 1.0)
execjs (2.5.2)
factory_girl (3.3.0)
activesupport (>= 3.0.0)
factory_girl_rails (3.3.0)
@@ -319,14 +320,14 @@ GEM
jquery-rails (2.2.2)
railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0)
json (1.8.2)
json (1.8.3)
json_spec (1.1.1)
multi_json (~> 1.0)
rspec (~> 2.0)
kaminari (0.14.1)
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
kgio (2.7.4)
kgio (2.9.3)
launchy (2.1.2)
addressable (~> 2.3)
letter_opener (1.0.0)
@@ -352,7 +353,7 @@ GEM
net-scp (1.1.2)
net-ssh (>= 2.6.5)
net-ssh (2.6.8)
newrelic_rpm (3.6.7.152)
newrelic_rpm (3.12.0.288)
nokogiri (1.6.6.2)
mini_portile (~> 0.6.0)
oj (2.1.2)
@@ -362,6 +363,9 @@ GEM
activesupport (>= 3.0.0)
cocaine (~> 0.5.3)
mime-types
parallel (1.4.1)
parallel_tests (1.3.7)
parallel
paypal-sdk-core (0.2.10)
multi_json (~> 1.0)
xml-simple
@@ -413,7 +417,7 @@ GEM
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
raindrops (0.9.0)
raindrops (0.13.0)
rake (10.4.2)
ransack (0.7.2)
actionpack (~> 3.0)
@@ -497,10 +501,10 @@ GEM
turn (0.8.3)
ansi
tzinfo (0.3.44)
uglifier (1.2.4)
uglifier (2.7.1)
execjs (>= 0.3.0)
multi_json (>= 1.0.2)
unicorn (4.3.1)
json (>= 1.8.0)
unicorn (4.9.0)
kgio (~> 2.6)
rack
raindrops (~> 0.7)
@@ -532,8 +536,9 @@ PLATFORMS
DEPENDENCIES
active_model_serializers
acts-as-taggable-on (~> 3.4)
andand
angular-rails-templates
angular-rails-templates (~> 0.2.0)
angularjs-file-upload-rails (~> 1.1.0)
angularjs-rails (= 1.2.13)
awesome_print
@@ -575,6 +580,7 @@ DEPENDENCIES
newrelic_rpm
oj
paperclip
parallel_tests
pg
poltergeist
pry-debugger

View File

@@ -1,3 +1,3 @@
angular.module("ofn.admin", ["ngResource", "ngAnimate", "ofn.dropdown", "admin.products", "admin.taxons", "infinite-scroll"]).config ($httpProvider) ->
angular.module("ofn.admin", ["ngResource", "ngAnimate", "admin.indexUtils", "admin.dropdown", "admin.products", "admin.taxons", "infinite-scroll"]).config ($httpProvider) ->
$httpProvider.defaults.headers.common["X-CSRF-Token"] = $("meta[name=csrf-token]").attr("content")
$httpProvider.defaults.headers.common["Accept"] = "application/json, text/javascript, */*"

View File

@@ -12,14 +12,21 @@
//= require angular
//= require angular-resource
//= require angular-animate
//= require angular-sanitize
//= require admin/spree_core
//= require admin/spree_auth
//= require admin/spree_promo
//= require admin/spree_paypal_express
//= require ../shared/ng-infinite-scroll.min.js
//= require ../shared/ng-tags-input.min.js
//= require angular-rails-templates
//= require_tree ../templates/admin
//= require ./admin
//= require ./customers/customers
//= require ./dropdown/dropdown
//= require ./enterprises/enterprises
//= require ./enterprise_groups/enterprise_groups
//= require ./index_utils/index_utils
//= require ./payment_methods/payment_methods
//= require ./products/products
//= require ./shipping_methods/shipping_methods
@@ -29,5 +36,6 @@
//= require ./users/users
//= require textAngular.min.js
//= require textAngular-sanitize.min.js
//= require ../shared/bindonce.min.js
//= require_tree .

View File

@@ -1,6 +1,6 @@
angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [
"$scope", "$http", "$filter", "dataFetcher", "blankOption", "pendingChanges", "VariantUnitManager", "OptionValueNamer", "SpreeApiKey"
($scope, $http, $filter, dataFetcher, blankOption, pendingChanges, VariantUnitManager, OptionValueNamer, SpreeApiKey) ->
"$scope", "$http", "$filter", "dataFetcher", "blankOption", "pendingChanges", "VariantUnitManager", "OptionValueNamer", "SpreeApiKey", "Columns"
($scope, $http, $filter, dataFetcher, blankOption, pendingChanges, VariantUnitManager, OptionValueNamer, SpreeApiKey, Columns) ->
$scope.loading = true
$scope.initialiseVariables = ->
@@ -18,9 +18,7 @@ angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [
$scope.selectedUnitsProduct = {};
$scope.selectedUnitsVariant = {};
$scope.sharedResource = false
$scope.predicate = ""
$scope.reverse = false
$scope.columns =
$scope.columns = Columns.setColumns
order_no: { name: "Order No.", visible: false }
full_name: { name: "Name", visible: true }
email: { name: "Email", visible: false }
@@ -32,7 +30,8 @@ angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [
variant: { name: "Variant", visible: true }
quantity: { name: "Quantity", visible: true }
max: { name: "Max", visible: true }
unit_value: { name: "Weight/Volume", visible: false }
price: { name: "Price", visible: false }
$scope.initialise = ->
$scope.initialiseVariables()
authorise_api_reponse = ""
@@ -62,7 +61,7 @@ angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [
$scope.fetchOrders = ->
$scope.loading = true
dataFetcher("/api/orders/managed?template=bulk_index;page=1;per_page=500;q[state_not_eq]=canceled;q[completed_at_not_null]=true;q[completed_at_gt]=#{$scope.startDate};q[completed_at_lt]=#{$scope.endDate}").then (data) ->
dataFetcher("/admin/orders/managed?template=bulk_index;page=1;per_page=500;q[state_not_eq]=canceled;q[completed_at_not_null]=true;q[completed_at_gt]=#{$scope.startDate};q[completed_at_lt]=#{$scope.endDate}").then (data) ->
$scope.resetOrders data
$scope.loading = false
@@ -165,6 +164,20 @@ angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [
$scope.orderCycleFilter = $scope.orderCycles[0].id
$scope.quickSearch = ""
$scope.weightAdjustedPrice = (lineItem, oldValue) ->
if oldValue <= 0
oldValue = lineItem.units_variant.unit_value
if lineItem.unit_value <= 0
lineItem.unit_value = lineItem.units_variant.unit_value
lineItem.price = lineItem.price * lineItem.unit_value / oldValue
#$scope.bulk_order_form.line_item.price.$setViewValue($scope.bulk_order_form.line_item.price.$viewValue)
$scope.unitValueLessThanZero = (lineItem) ->
if lineItem.units_variant.unit_value <= 0
true
else
false
$scope.$watch "orderCycleFilter", (newVal, oldVal) ->
unless $scope.orderCycleFilter == "0" || angular.equals(newVal, oldVal)
$scope.startDate = $scope.orderCyclesByID[$scope.orderCycleFilter].first_order

View File

@@ -1,16 +1,18 @@
angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout, $http, BulkProducts, DisplayProperties, dataFetcher, DirtyProducts, VariantUnitManager, StatusMessage, producers, Taxons, SpreeApiAuth) ->
angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout, $http, BulkProducts, DisplayProperties, dataFetcher, DirtyProducts, VariantUnitManager, StatusMessage, producers, Taxons, SpreeApiAuth, Columns, tax_categories) ->
$scope.loading = true
$scope.StatusMessage = StatusMessage
$scope.columns =
$scope.columns = Columns.setColumns
producer: {name: "Producer", visible: true}
sku: {name: "SKU", visible: false}
name: {name: "Name", visible: true}
unit: {name: "Unit", visible: true}
price: {name: "Price", visible: true}
on_hand: {name: "On Hand", visible: true}
on_demand: {name: "On Demand", visible: false}
category: {name: "Category", visible: false}
tax_category: {name: "Tax Category", visible: false}
inherits_properties: {name: "Inherits Properties?", visible: false}
available_on: {name: "Available On", visible: false}
@@ -32,6 +34,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
$scope.producers = producers
$scope.taxons = Taxons.taxons
$scope.tax_categories = tax_categories
$scope.filterProducers = [{id: "0", name: ""}].concat $scope.producers
$scope.filterTaxons = [{id: "0", name: ""}].concat $scope.taxons
$scope.producerFilter = "0"
@@ -106,6 +109,12 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
window.location = "/admin/products/" + product.permalink_live + ((if variant then "/variants/" + variant.id else "")) + "/edit"
$scope.toggleShowAllVariants = ->
showVariants = !DisplayProperties.showVariants 0
$scope.filteredProducts.forEach (product) ->
DisplayProperties.setShowVariants product.id, showVariants
DisplayProperties.setShowVariants 0, showVariants
$scope.addVariant = (product) ->
product.variants.push
id: $scope.nextVariantId()
@@ -137,15 +146,18 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
$scope.deleteVariant = (product, variant) ->
if !$scope.variantSaved(variant)
$scope.removeVariant(product, variant)
if product.variants.length > 1
if !$scope.variantSaved(variant)
$scope.removeVariant(product, variant)
else
if confirm("Are you sure?")
$http(
method: "DELETE"
url: "/api/products/" + product.permalink_live + "/variants/" + variant.id + "/soft_delete"
).success (data) ->
$scope.removeVariant(product, variant)
else
if confirm("Are you sure?")
$http(
method: "DELETE"
url: "/api/products/" + product.permalink_live + "/variants/" + variant.id + "/soft_delete"
).success (data) ->
$scope.removeVariant(product, variant)
alert("The last variant cannot be deleted!")
$scope.removeVariant = (product, variant) ->
product.variants.splice product.variants.indexOf(variant), 1
@@ -309,9 +321,15 @@ filterSubmitProducts = (productsToFilter) ->
if product.hasOwnProperty("on_hand") and filteredVariants.length == 0 #only update if no variants present
filteredProduct.on_hand = product.on_hand
hasUpdatableProperty = true
if product.hasOwnProperty("on_demand") and filteredVariants.length == 0 #only update if no variants present
filteredProduct.on_demand = product.on_demand
hasUpdatableProperty = true
if product.hasOwnProperty("category_id")
filteredProduct.primary_taxon_id = product.category_id
hasUpdatableProperty = true
if product.hasOwnProperty("tax_category_id")
filteredProduct.tax_category_id = product.tax_category_id
hasUpdatableProperty = true
if product.hasOwnProperty("inherits_properties")
filteredProduct.inherits_properties = product.inherits_properties
hasUpdatableProperty = true
@@ -337,6 +355,9 @@ filterSubmitVariant = (variant) ->
if variant.hasOwnProperty("on_hand")
filteredVariant.on_hand = variant.on_hand
hasUpdatableProperty = true
if variant.hasOwnProperty("on_demand")
filteredVariant.on_demand = variant.on_demand
hasUpdatableProperty = true
if variant.hasOwnProperty("price")
filteredVariant.price = variant.price
hasUpdatableProperty = true

View File

@@ -9,3 +9,26 @@ angular.module("ofn.admin").controller "AdminEnterpriseRelationshipsCtrl", ($sco
$scope.delete = (enterprise_relationship) ->
if confirm("Are you sure?")
$scope.EnterpriseRelationships.delete enterprise_relationship
$scope.toggleKeyword = (string, key) ->
string = '' unless string
words = string.split ' '
words = words.filter (s) ->
s
index = words.indexOf key
if index > -1
words.splice index, 1
else
words.push key
words.join ' '
$scope.allPermissionsChecked = ->
for i in EnterpriseRelationships.all_permissions
if !$scope.permissions[i]
return false
return true
$scope.checkAllPermissions = ->
newValue = !$scope.allPermissionsChecked()
EnterpriseRelationships.all_permissions.forEach (p) ->
$scope.permissions[p] = newValue

View File

@@ -0,0 +1,17 @@
angular.module("admin.customers").controller "customersCtrl", ($scope, Customers, Columns, pendingChanges, shops) ->
$scope.shop = null
$scope.shops = shops
$scope.submitAll = pendingChanges.submitAll
$scope.columns = Columns.setColumns
email: { name: "Email", visible: true }
code: { name: "Code", visible: true }
tags: { name: "Tags", visible: true }
$scope.$watch "shop", ->
if $scope.shop?
Customers.loaded = false
$scope.customers = Customers.index(enterprise_id: $scope.shop.id)
$scope.loaded = ->
Customers.loaded

View File

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

View File

@@ -0,0 +1,8 @@
angular.module("admin.customers").directive "tagsWithTranslation", ->
restrict: "E"
template: "<tags-input ng-model='object.tags'>"
scope:
object: "="
link: (scope, element, attrs) ->
scope.$watchCollection "object.tags", ->
scope.object.tag_list = (tag.text for tag in scope.object.tags).join(",")

View File

@@ -0,0 +1,8 @@
angular.module("admin.customers").factory 'CustomerResource', ($resource) ->
$resource('/admin/customers.json', {}, {
'index':
method: 'GET'
isArray: true
params:
enterprise_id: '@enterprise_id'
})

View File

@@ -0,0 +1,16 @@
angular.module("admin.customers").factory 'Customers', (CustomerResource) ->
new class Customers
customers: []
customers_by_id: {}
loaded: false
index: (params={}, callback=null) ->
CustomerResource.index params, (data) =>
for customer in data
@customers.push customer
@customers_by_id[customer.id] = customer
@loaded = true
(callback || angular.noop)(@customers)
@customers

View File

@@ -1,23 +0,0 @@
angular.module("ofn.admin").directive "ofnLineItemUpdAttr", [
"switchClass", "pendingChanges"
(switchClass, pendingChanges) ->
require: "ngModel"
link: (scope, element, attrs, ngModel) ->
attrName = attrs.ofnLineItemUpdAttr
element.dbValue = scope.$eval(attrs.ngModel)
scope.$watch ->
scope.$eval(attrs.ngModel)
, (value) ->
if ngModel.$dirty
if value == element.dbValue
pendingChanges.remove(scope.line_item.id, attrName)
switchClass( element, "", ["update-pending", "update-error", "update-success"], false )
else
changeObj =
lineItem: scope.line_item
element: element
attrName: attrName
url: "/api/orders/#{scope.line_item.order.number}/line_items/#{scope.line_item.id}?line_item[#{attrName}]=#{value}"
pendingChanges.add(scope.line_item.id, attrName, changeObj)
switchClass( element, "update-pending", ["update-error", "update-success"], false )
]

View File

@@ -1,11 +0,0 @@
angular.module("ofn.admin").directive "ofnToggleColumn", ->
link: (scope, element, attrs) ->
element.addClass "selected" if scope.column.visible
element.click "click", ->
scope.$apply ->
if scope.column.visible
scope.column.visible = false
element.removeClass "selected"
else
scope.column.visible = true
element.addClass "selected"

View File

@@ -1,10 +1,8 @@
angular.module("ofn.admin").directive "ofnToggleVariants", (DisplayProperties) ->
link: (scope, element, attrs) ->
if DisplayProperties.showVariants scope.product.id
element.removeClass "icon-chevron-right"
element.addClass "icon-chevron-down"
else
element.removeClass "icon-chevron-down"
element.addClass "icon-chevron-right"
element.on "click", ->
@@ -16,4 +14,4 @@ angular.module("ofn.admin").directive "ofnToggleVariants", (DisplayProperties) -
else
DisplayProperties.setShowVariants scope.product.id, true
element.removeClass "icon-chevron-right"
element.addClass "icon-chevron-down"
element.addClass "icon-chevron-down"

View File

@@ -0,0 +1,2 @@
angular.module("admin.dropdown").controller "DropDownCtrl", ($scope) ->
$scope.expanded = false

View File

@@ -0,0 +1,5 @@
angular.module("admin.dropdown").directive "ofnCloseOnClick", ($document) ->
link: (scope, element, attrs) ->
element.click (event) ->
event.stopPropagation()
scope.$emit "offClick"

View File

@@ -1,6 +1,4 @@
dropDownModule = angular.module("ofn.dropdown", [])
dropDownModule.directive "ofnDropDown", ($document) ->
angular.module("admin.dropdown").directive "ofnDropDown", ($document) ->
link: (scope, element, attrs) ->
outsideClickListener = (event) ->
unless $(event.target).is("div.ofn_drop_down##{attrs.id} div.menu") ||
@@ -20,12 +18,3 @@ dropDownModule.directive "ofnDropDown", ($document) ->
scope.$apply ->
scope.expanded = true
element.addClass "expanded"
dropDownModule.directive "ofnCloseOnClick", ($document) ->
link: (scope, element, attrs) ->
element.click (event) ->
event.stopPropagation()
scope.$emit "offClick"
dropDownModule.controller "DropDownCtrl", ($scope) ->
$scope.expanded = false

View File

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

View File

@@ -1,6 +1,6 @@
angular.module("admin.enterprises")
.controller "enterpriseCtrl", ($scope, NavigationCheck, Enterprise, EnterprisePaymentMethods, EnterpriseShippingMethods, SideMenu) ->
$scope.Enterprise = Enterprise.enterprise
.controller "enterpriseCtrl", ($scope, NavigationCheck, enterprise, EnterprisePaymentMethods, EnterpriseShippingMethods, SideMenu) ->
$scope.Enterprise = enterprise
$scope.PaymentMethods = EnterprisePaymentMethods.paymentMethods
$scope.ShippingMethods = EnterpriseShippingMethods.shippingMethods
$scope.navClear = NavigationCheck.clear

View File

@@ -0,0 +1,49 @@
angular.module("admin.enterprises").controller "EnterpriseIndexRowCtrl", ($scope) ->
$scope.status = ->
if $scope.enterprise.issues.length > 0
"issue"
else if $scope.enterprise.warnings.length > 0
"warning"
else
"ok"
$scope.producerText = ->
switch $scope.enterprise.is_primary_producer
when true
"Producer"
else
"Non-Producer"
$scope.packageText = ->
switch $scope.enterprise.is_primary_producer
when true
switch $scope.enterprise.sells
when "none"
"Profile"
when "own"
"Shop"
when "any"
"Hub"
else
"Choose"
else
switch $scope.enterprise.sells
when "none"
"Profile"
when "any"
"Hub"
else
"Choose"
$scope.updateRowText = ->
$scope.producer = $scope.producerText()
$scope.package = $scope.packageText()
$scope.producerError = ($scope.producer == "Choose")
$scope.packageError = ($scope.package == "Choose")
$scope.updateRowText()
$scope.$on "enterprise:updated", ->
$scope.updateRowText()

View File

@@ -0,0 +1,13 @@
angular.module("admin.enterprises").controller 'enterprisesCtrl', ($scope, Enterprises, Columns) ->
Enterprises.loaded = false
$scope.allEnterprises = Enterprises.index()
$scope.loaded = ->
Enterprises.loaded
$scope.columns = Columns.setColumns
name: { name: "Name", visible: true }
producer: { name: "Producer", visible: true }
package: { name: "Package", visible: true }
status: { name: "Status", visible: true }
manage: { name: "Manage", visible: true }

View File

@@ -0,0 +1,2 @@
angular.module("admin.enterprises").controller 'indexPackagePanelCtrl', ($scope, $controller) ->
angular.extend this, $controller('indexPanelCtrl', {$scope: $scope})

View File

@@ -0,0 +1,23 @@
angular.module("admin.enterprises").controller 'indexPanelCtrl', ($scope, Enterprises) ->
$scope.enterprise = $scope.object
$scope.saving = false
$scope.saved = ->
Enterprises.saved($scope.enterprise)
$scope.save = ->
unless $scope.saved()
$scope.saving = true
Enterprises.save($scope.enterprise).then (data) ->
$scope.$emit("enterprise:updated")
$scope.saving = false
, (response) ->
$scope.saving = false
if response.status == 422 && response.data.errors?
message = 'Please resolve the following errors:\n'
for attr, msg of response.data.errors
message += "#{attr} #{msg}\n"
alert(message)
$scope.resetAttribute = (attribute) ->
Enterprises.resetAttribute($scope.enterprise, attribute)

View File

@@ -0,0 +1,14 @@
angular.module("admin.enterprises").controller 'indexProducerPanelCtrl', ($scope, $controller) ->
angular.extend this, $controller('indexPanelCtrl', {$scope: $scope})
$scope.changeToProducer = ->
$scope.resetAttribute('sells')
$scope.resetAttribute('producer_profile_only')
$scope.enterprise.is_primary_producer = true
$scope.changeToNonProducer = ->
if $scope.enterprise.sells == 'own'
$scope.enterprise.sells = 'any'
if $scope.enterprise.producer_profile_only = true
$scope.enterprise.producer_profile_only = false
$scope.enterprise.is_primary_producer = false

View File

@@ -0,0 +1,3 @@
angular.module("admin.enterprises").controller 'indexStatusPanelCtrl', ($scope, $filter) ->
$scope.issues = $scope.object.issues
$scope.warnings = $scope.object.warnings

View File

@@ -1,6 +1,6 @@
angular.module("admin.enterprises")
.controller "sideMenuCtrl", ($scope, $parse, Enterprise, SideMenu, enterprisePermissions) ->
$scope.Enterprise = Enterprise.enterprise
.controller "sideMenuCtrl", ($scope, $parse, enterprise, SideMenu, enterprisePermissions) ->
$scope.Enterprise = enterprise
$scope.menu = SideMenu
$scope.select = SideMenu.select

View File

@@ -1 +1 @@
angular.module("admin.enterprises", [
angular.module("admin.enterprises", [

View File

@@ -1,11 +1,11 @@
angular.module("admin.enterprises")
.factory "EnterprisePaymentMethods", (Enterprise, PaymentMethods) ->
.factory "EnterprisePaymentMethods", (enterprise, PaymentMethods) ->
new class EnterprisePaymentMethods
paymentMethods: PaymentMethods.paymentMethods
constructor: ->
for payment_method in @paymentMethods
payment_method.selected = payment_method.id in Enterprise.enterprise.payment_method_ids
payment_method.selected = payment_method.id in enterprise.payment_method_ids
displayColor: ->
if @paymentMethods.length > 0 && @selectedCount() > 0

View File

@@ -0,0 +1,8 @@
angular.module("admin.enterprises").factory 'EnterpriseResource', ($resource) ->
$resource('/admin/enterprises/:id.json', {}, {
'index':
method: 'GET'
isArray: true
'update':
method: 'PUT'
})

View File

@@ -1,11 +1,11 @@
angular.module("admin.enterprises")
.factory "EnterpriseShippingMethods", (Enterprise, ShippingMethods) ->
.factory "EnterpriseShippingMethods", (enterprise, ShippingMethods) ->
new class EnterpriseShippingMethods
shippingMethods: ShippingMethods.shippingMethods
constructor: ->
for shipping_method in @shippingMethods
shipping_method.selected = shipping_method.id in Enterprise.enterprise.shipping_method_ids
shipping_method.selected = shipping_method.id in enterprise.shipping_method_ids
displayColor: ->
if @shippingMethods.length > 0 && @selectedCount() > 0

View File

@@ -0,0 +1,39 @@
angular.module("admin.enterprises").factory 'Enterprises', ($q, EnterpriseResource) ->
new class Enterprises
enterprises: []
enterprises_by_id: {}
pristine_by_id: {}
loaded: false
index: (params={}, callback=null) ->
EnterpriseResource.index params, (data) =>
for enterprise in data
@enterprises.push enterprise
@pristine_by_id[enterprise.id] = angular.copy(enterprise)
@loaded = true
(callback || angular.noop)(@enterprises)
@enterprises
save: (enterprise) ->
deferred = $q.defer()
enterprise.$update({id: enterprise.permalink})
.then( (data) =>
@pristine_by_id[enterprise.id] = angular.copy(enterprise)
deferred.resolve(data)
).catch (response) ->
deferred.reject(response)
deferred.promise
saved: (enterprise) ->
@diff(enterprise).length == 0
diff: (enterprise) ->
changed = []
for attr, value of enterprise when not angular.equals(value, @pristine_by_id[enterprise.id][attr])
changed.push attr unless attr is "$$hashKey"
changed
resetAttribute: (enterprise, attribute) ->
enterprise[attribute] = @pristine_by_id[enterprise.id][attribute]

View File

@@ -0,0 +1,7 @@
angular.module("ofn.admin").filter "keywords", ($filter) ->
return (array, query) ->
return array unless query
keywords = query.split ' '
keywords.forEach (key) ->
array = $filter('filter')(array, key)
array

View File

@@ -0,0 +1,4 @@
angular.module("admin.indexUtils").controller "ColumnsCtrl", ($scope, Columns) ->
$scope.columns = Columns.columns
$scope.predicate = ""
$scope.reverse = false

View File

@@ -0,0 +1,36 @@
angular.module("admin.indexUtils").directive "objForUpdate", (switchClass, pendingChanges) ->
scope:
object: "&objForUpdate"
type: "@objForUpdate"
attr: "@attrForUpdate"
link: (scope, element, attrs) ->
scope.savedValue = scope.object()[scope.attr]
scope.$watch "object().#{scope.attr}", (value) ->
if value == scope.savedValue
pendingChanges.remove(scope.object().id, scope.attr)
scope.clear()
else
change =
object: scope.object()
type: scope.type
attr: scope.attr
value: value
scope: scope
scope.pending()
pendingChanges.add(scope.object().id, scope.attr, change)
scope.reset = (value) ->
scope.savedValue = value
scope.success = ->
switchClass( element, "update-success", ["update-pending", "update-error"], 3000 )
scope.pending = ->
switchClass( element, "update-pending", ["update-error", "update-success"], false )
scope.error = ->
switchClass( element, "update-error", ["update-pending", "update-success"], false )
scope.clear = ->
switchClass( element, "", ["update-pending", "update-error", "update-success"], false )

View File

@@ -0,0 +1,37 @@
angular.module("admin.indexUtils").directive "panelRow", (Panels, Columns) ->
restrict: "C"
templateUrl: "admin/panel.html"
scope:
object: "="
panels: "="
link: (scope, element, attrs) ->
scope.template = ""
selected = null
scope.columnCount = Columns.visibleCount
scope.$on "columnCount:changed", (event, count) ->
scope.columnCount = count
setTemplate = ->
if selected?
scope.template = 'admin/panels/' + scope.panels[selected] + '.html'
else
scope.template = ""
scope.getSelected = ->
selected
scope.setSelected = (name) ->
scope.$apply ->
selected = name
setTemplate()
scope.open = (name) ->
element.show 0, ->
scope.setSelected name
scope.close = ->
element.hide 0, ->
scope.setSelected null
Panels.register(scope.object.id, scope)

View File

@@ -0,0 +1,12 @@
angular.module("admin.indexUtils").directive "panelToggle", ->
restrict: "C"
transclude: true
template: '<div ng-transclude></div><i class=\'icon-chevron\'></i>'
require: "^panelToggleRow"
scope:
name: "@"
link: (scope, element, attrs, ctrl) ->
scope.selected = ctrl.register(scope.name, element)
element.on "click", ->
scope.selected = ctrl.select(scope.name)

View File

@@ -0,0 +1,29 @@
angular.module("admin.indexUtils").directive "panelToggleRow", (Panels) ->
restrict: "C"
scope:
object: "="
selected: "@?"
controller: ($scope) ->
panelToggles = {}
this.register = (name, element) ->
panelToggles[name] = element
panelToggles[name].addClass("selected") if $scope.selected == name
$scope.selected == name
this.select = (name) ->
panelToggle.removeClass("selected") for panelName, panelToggle of panelToggles
switch $scope.selected = Panels.toggle($scope.object.id, name)
when null
panelToggles[name].parent(".panel-toggle-row").removeClass("expanded")
else
panelToggles[$scope.selected].addClass("selected")
panelToggles[$scope.selected].parent(".panel-toggle-row").addClass("expanded")
$scope.selected == name
this
#
# link: (scope, element, attrs) ->
# Panels.registerInitialSelection(scope.object.id, scope.selected)

View File

@@ -0,0 +1,8 @@
angular.module("admin.indexUtils").directive "ofnToggleColumn", (Columns) ->
link: (scope, element, attrs) ->
element.addClass "selected" if scope.column.visible
element.click "click", ->
scope.$apply ->
Columns.toggleColumn(scope.column)
element.toggleClass "selected"

View File

@@ -0,0 +1 @@
angular.module("admin.indexUtils", ['ngResource', 'templates']).config ($httpProvider) ->

View File

@@ -0,0 +1,18 @@
angular.module("admin.indexUtils").factory 'Columns', ($rootScope) ->
new class Columns
columns: {}
visibleCount: 0
setColumns: (columns) =>
@columns = {}
@columns[name] = column for name, column of columns
@calculateVisibleCount()
@columns
toggleColumn: (column) =>
column.visible = !column.visible
@calculateVisibleCount()
calculateVisibleCount: =>
@visibleCount = (column for name, column of @columns when column.visible).length
$rootScope.$broadcast "columnCount:changed", @visibleCount

View File

@@ -0,0 +1,19 @@
angular.module("admin.indexUtils").factory 'Panels', ->
new class Panels
panels: {}
register: (id, scope) ->
if id? && scope?
@panels[id] = scope
toggle: (id, name) ->
scope = @panels[id]
selected = scope.getSelected()
switch selected
when name
scope.close()
when null
scope.open(name)
else
scope.setSelected(name)
scope.getSelected()

View File

@@ -0,0 +1,33 @@
angular.module("admin.indexUtils").factory "pendingChanges", (resources) ->
new class pendingChanges
pendingChanges: {}
add: (id, attr, change) =>
@pendingChanges["#{id}"] = {} unless @pendingChanges.hasOwnProperty("#{id}")
@pendingChanges["#{id}"]["#{attr}"] = change
removeAll: =>
@pendingChanges = {}
remove: (id, attr) =>
if @pendingChanges.hasOwnProperty("#{id}")
delete @pendingChanges["#{id}"]["#{attr}"]
delete @pendingChanges["#{id}"] if @changeCount( @pendingChanges["#{id}"] ) < 1
submitAll: =>
all = []
for id, objectChanges of @pendingChanges
for attrName, change of objectChanges
all.push @submit(change)
all
submit: (change) ->
resources.update(change).$promise.then (data) =>
@remove change.object.id, change.attr
change.scope.reset( data["#{change.attr}"] )
change.scope.success()
, (error) ->
change.scope.error()
changeCount: (objectChanges) ->
Object.keys(objectChanges).length

View File

@@ -0,0 +1,30 @@
angular.module("admin.indexUtils").factory "resources", ($resource) ->
LineItem = $resource '/api/orders/:order_number/line_items/:line_item_id.json',
{ order_number: '@order_number', line_item_id: '@line_item_id'},
'update': { method: 'PUT' }
Customer = $resource '/admin/customers/:customer_id.json',
{ customer_id: '@customer_id'},
'update': { method: 'PUT' }
return {
update: (change) ->
params = {}
data = {}
resource = null
switch change.type
when "line_item"
resource = LineItem
params.order_number = change.object.order.number
params.line_item_id = change.object.id
data.line_item = {}
data.line_item[change.attr] = change.value
when "customer"
resource = Customer
params.customer_id = change.object.id
data.customer = {}
data.customer[change.attr] = change.value
else ""
resource.update(params, data)
}

View File

@@ -0,0 +1,10 @@
angular.module("admin.indexUtils").factory "switchClass", ($timeout) ->
return (element,classToAdd,removeClasses,timeout) ->
$timeout.cancel element.timeout if element.timeout
element.removeClass className for className in removeClasses
element.addClass classToAdd
intRegex = /^\d+$/
if timeout && intRegex.test(timeout)
element.timeout = $timeout(->
element.removeClass classToAdd
, timeout, true)

View File

@@ -5,6 +5,13 @@ angular.module("admin.products")
$scope.placeholder_text = ""
$scope.$watchCollection '[product.variant_unit_with_scale, product.master.unit_value_with_description]', ->
$scope.processVariantUnitWithScale()
$scope.processUnitValueWithDescription()
$scope.placeholder_text = new OptionValueNamer($scope.product.master).name()
$scope.variant_unit_options = VariantUnitManager.variantUnitOptions()
$scope.processVariantUnitWithScale = ->
if $scope.product.variant_unit_with_scale
match = $scope.product.variant_unit_with_scale.match(/^([^_]+)_([\d\.]+)$/)
if match
@@ -16,18 +23,15 @@ angular.module("admin.products")
else
$scope.product.variant_unit = $scope.product.variant_unit_scale = null
$scope.processUnitValueWithDescription = ->
if $scope.product.master.hasOwnProperty("unit_value_with_description")
match = $scope.product.master.unit_value_with_description.match(/^([\d\.]+(?= |$)|)( |)(.*)$/)
match = $scope.product.master.unit_value_with_description.match(/^([\d\.]+(?= *|$)|)( *)(.*)$/)
if match
$scope.product.master.unit_value = parseFloat(match[1])
$scope.product.master.unit_value = null if isNaN($scope.product.master.unit_value)
$scope.product.master.unit_value *= $scope.product.variant_unit_scale if $scope.product.master.unit_value && $scope.product.variant_unit_scale
$scope.product.master.unit_description = match[3]
$scope.placeholder_text = new OptionValueNamer($scope.product.master).name()
$scope.variant_unit_options = VariantUnitManager.variantUnitOptions()
$scope.hasVariants = (product) ->
Object.keys(product.variants).length > 0

View File

@@ -19,7 +19,7 @@ angular.module("ofn.admin").factory "BulkProducts", (PagedFetcher, dataFetcher)
# when a respond_overrride for the clone action is used.
id = data.product.id
dataFetcher("/api/products/" + id + "?template=bulk_show").then (newProduct) =>
@addProducts [newProduct]
@insertProductAfter(product, newProduct)
updateVariantLists: (serverProducts, productsWithUnsavedVariants) ->
for product in productsWithUnsavedVariants
@@ -39,6 +39,10 @@ angular.module("ofn.admin").factory "BulkProducts", (PagedFetcher, dataFetcher)
@unpackProduct product
@products.push product
insertProductAfter: (product, newProduct) ->
index = @products.indexOf(product)
@products.splice(index + 1, 0, newProduct)
unpackProduct: (product) ->
#$scope.matchProducer product
@loadVariantUnit product

View File

@@ -1,13 +0,0 @@
angular.module("ofn.admin").factory "dataSubmitter", [
"$http", "$q", "switchClass"
($http, $q, switchClass) ->
return (changeObj) ->
deferred = $q.defer()
$http.put(changeObj.url).success((data) ->
switchClass changeObj.element, "update-success", ["update-pending", "update-error"], 3000
deferred.resolve data
).error ->
switchClass changeObj.element, "update-error", ["update-pending", "update-success"], false
deferred.reject()
deferred.promise
]

View File

@@ -3,12 +3,10 @@ angular.module("ofn.admin").factory "DisplayProperties", ->
displayProperties: {}
showVariants: (product_id) ->
@initProduct product_id
@displayProperties[product_id].showVariants
@productProperties(product_id).showVariants
setShowVariants: (product_id, showVariants) ->
@initProduct product_id
@displayProperties[product_id].showVariants = showVariants
@productProperties(product_id).showVariants = showVariants
initProduct: (product_id) ->
productProperties: (product_id) ->
@displayProperties[product_id] ||= {showVariants: false}

View File

@@ -26,7 +26,7 @@ angular.module("ofn.admin").factory 'EnterpriseRelationships', ($http, enterpris
permission_presentation: (permission) ->
switch permission
when "add_to_order_cycle" then "to add to order cycle"
when "manage_products" then "to manage products"
when "edit_profile" then "to edit profile"
when "create_variant_overrides" then "to override variant details"
when "add_to_order_cycle" then "add to order cycle"
when "manage_products" then "manage products"
when "edit_profile" then "edit profile"
when "create_variant_overrides" then "override variant details"

View File

@@ -1,32 +0,0 @@
angular.module("ofn.admin").factory "pendingChanges",[
"dataSubmitter"
(dataSubmitter) ->
pendingChanges: {}
add: (id, attrName, changeObj) ->
@pendingChanges["#{id}"] = {} unless @pendingChanges.hasOwnProperty("#{id}")
@pendingChanges["#{id}"]["#{attrName}"] = changeObj
removeAll: ->
@pendingChanges = {}
remove: (id, attrName) ->
if @pendingChanges.hasOwnProperty("#{id}")
delete @pendingChanges["#{id}"]["#{attrName}"]
delete @pendingChanges["#{id}"] if @changeCount( @pendingChanges["#{id}"] ) < 1
submitAll: ->
all = []
for id,lineItem of @pendingChanges
for attrName,changeObj of lineItem
all.push @submit(id, attrName, changeObj)
all
submit: (id, attrName, change) ->
dataSubmitter(change).then (data) =>
@remove id, attrName
change.element.dbValue = data["#{attrName}"]
changeCount: (lineItem) ->
Object.keys(lineItem).length
]

View File

@@ -1,13 +0,0 @@
angular.module("ofn.admin").factory "switchClass", [
"$timeout"
($timeout) ->
return (element,classToAdd,removeClasses,timeout) ->
$timeout.cancel element.timeout if element.timeout
element.removeClass className for className in removeClasses
element.addClass classToAdd
intRegex = /^\d+$/
if timeout && intRegex.test(timeout)
element.timeout = $timeout(->
element.removeClass classToAdd
, timeout, true)
]

View File

@@ -1,9 +1,10 @@
Darkswarm.controller "GroupEnterprisesCtrl", ($scope, Search, FilterSelectorsService) ->
Darkswarm.controller "GroupEnterprisesCtrl", ($scope, Search, FilterSelectorsService, EnterpriseModal) ->
$scope.totalActive = FilterSelectorsService.totalActive
$scope.clearAll = FilterSelectorsService.clearAll
$scope.filterText = FilterSelectorsService.filterText
$scope.FilterSelectorsService = FilterSelectorsService
$scope.query = Search.search()
$scope.openModal = EnterpriseModal.open
$scope.activeTaxons = []
$scope.show_profiles = false
$scope.filtersActive = false

View File

@@ -1,8 +1,3 @@
Darkswarm.controller "GroupsCtrl", ($scope, Groups, $anchorScroll, $rootScope) ->
$scope.Groups = Groups
$scope.order = 'position'
#$rootScope.$on "$locationChangeSuccess", (newRoute, oldRoute) ->
#$anchorScroll()
#
#

View File

@@ -1,6 +1,6 @@
Darkswarm.controller "HubNodeCtrl", ($scope, HashNavigation, Navigation, $location, $templateCache, CurrentHub) ->
$scope.toggle = ->
HashNavigation.toggle $scope.hub.hash
$scope.toggle = (e) ->
HashNavigation.toggle $scope.hub.hash if !angular.element(e.target).inheritedData('is-link')
$scope.open = ->
HashNavigation.active $scope.hub.hash

View File

@@ -22,17 +22,11 @@ Darkswarm.directive "filterSelector", (FilterSelectorsService)->
.map (selector)->
selector.object.id
# This can be called from a parent scope
# when data has been loaded, in order to pass
# selectors up
scope.$on 'loadFilterSelectors', ->
scope.allSelectors = scope.selectors() if attr.allSelectors?
scope.$watchCollection "selectors()", (newValue, oldValue) ->
scope.allSelectors = scope.selectors() if attr.allSelectors?
scope.$watchCollection "objects()", (newValue, oldValue) ->
scope.allSelectors = scope.buildSelectors()
# Build a list of selectors
scope.selectors = ->
scope.buildSelectors = ->
# Generate a selector for each object.
# NOTE: THESE ARE MEMOIZED to stop new selectors from being created constantly, otherwise function always returns non-identical results
# This means the $digest cycle can never close and times out

View File

@@ -7,5 +7,5 @@ Darkswarm.factory "MapConfiguration", ->
zoom: 12
additional_options: {}
#mapTypeId: 'satellite'
styles: [{"featureType":"landscape","stylers":[{"saturation":-100},{"lightness":65},{"visibility":"on"}]},{"featureType":"poi","stylers":[{"saturation":-100},{"lightness":51},{"visibility":"simplified"}]},{"featureType":"road.highway","stylers":[{"saturation":-100},{"visibility":"simplified"}]},{"featureType":"road.arterial","stylers":[{"saturation":-100},{"lightness":30},{"visibility":"on"}]},{"featureType":"road.local","stylers":[{"saturation":-100},{"lightness":40},{"visibility":"on"}]},{"featureType":"transit","stylers":[{"saturation":-100},{"visibility":"simplified"}]},{"featureType":"administrative.province","stylers":[{"visibility":"off"}]},{"featureType":"water","elementType":"labels","stylers":[{"visibility":"on"},{"lightness":-25},{"saturation":-100}]},{"featureType":"water","elementType":"geometry","stylers":[{"hue":"#ffff00"},{"lightness":-25},{"saturation":-97}]}]
styles: [{"featureType":"landscape","stylers":[{"saturation":-100},{"lightness":65},{"visibility":"on"}]},{"featureType":"poi","stylers":[{"saturation":-100},{"lightness":51},{"visibility":"simplified"}]},{"featureType":"road.highway","stylers":[{"saturation":-100},{"visibility":"simplified"}]},{"featureType":"road.arterial","stylers":[{"saturation":-100},{"lightness":30},{"visibility":"on"}]},{"featureType":"road.local","stylers":[{"saturation":-100},{"lightness":40},{"visibility":"on"}]},{"featureType":"transit","stylers":[{"saturation":-100},{"visibility":"simplified"}]},{"featureType":"administrative.province","stylers":[{"visibility":"off"}]},{"featureType":"water","elementType":"labels","stylers":[{"visibility":"on"},{"lightness":-25},{"saturation":-100}]},{"featureType":"water","elementType":"geometry","stylers":[{"hue":"#ffff00"},{"lightness":-25},{"saturation":-97}]},{"featureType":"road","elementType": "labels.icon","stylers":[{"visibility":"off"}]}]

View File

@@ -32,8 +32,9 @@ Darkswarm.factory 'Products', ($resource, Enterprises, Dereferencer, Taxons, Pro
if product.variants
product.variants = (Variants.register variant for variant in product.variants)
variant.product = product for variant in product.variants
product.master.product = product
product.master = Variants.register product.master if product.master
if product.master
product.master.product = product
product.master = Variants.register product.master
registerVariantsWithCart: ->
for product in @products

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
%td{ colspan: "{{columnCount}}" }
.panel{ ng: { include: "template" } }

View File

@@ -0,0 +1,133 @@
.row.enterprise_package_panel{ ng: { controller: 'indexPackagePanelCtrl' } }
.alpha.eight.columns
%div{ ng: { if: "!enterprise.is_primary_producer", switch: "enterprise.sells" } }
.info{ ng: { switch: { when: "none" } } }
%h3 Hub Profile
%p
%strong COST: ALWAYS FREE
%p People can find and contact you on the Open Food Network. Your enterprise will be visible on the map, and will be searchable in listings.
%p Having a profile, and making connections within your local food system through the Open Food Network will always be free.
.info{ ng: { switch: { when: "any" } } }
%h3 Hub Shop
%p
%strong COST: 2% OF SALES, CAPPED AT $50 PER MONTH
%p Your enterprise is the backbone of your local food system. You aggregate produce from other enterprises and can sell it through your shop on the Open Food Network.
%p Hubs can take many forms, whether they be a food co-op, a buying group, a veggie-box program, or a local grocery store.
%p If you also want to sell your own products, you will need to switch this enterprise to be a producer.
.info{ ng: { switch: { default: true } } }
%h3
Please Choose a Package
%i.icon-arrow-right
%p
%strong Your enterprise will not be fully activated until a package is selected from the options on the left.
%p
Click on an option to see more detailed information about each package, and hit the red SAVE button when you are done!
%div{ ng: { if: "enterprise.is_primary_producer", switch: "enterprise.sells" } }
.info{ ng: { switch: { when: "none" } } }
%h3 Profile Only
%p
%strong COST: ALWAYS FREE
%p A profile makes you visible and contactable to others and is a way to share your story.
%p If you prefer to focus on producing food, and want to leave the work of selling it to someone else, you won't require a shop on the Open Food Network.
%p Add your products to Open Food Network, allowing hubs to stock your products in their stores.
.info{ ng: { switch: { when: "own" } } }
%h3 Producer Shop
%p
%strong COST: 2% OF SALES, CAPPED AT $50 PER MONTH
%p Sell your products directly to customers through your very own Open Food Network shopfront.
%p A Producer Shop is for your produce only, if you want to sell produce grown/produced off site, please select 'Producer Hub'.
.info{ ng: { switch: { when: "any" } } }
%h3 Producer Hub
%p
%strong COST: 2% OF SALES, CAPPED AT $50 PER MONTH
%p Your enterprise is the backbone of your local food system. You can sell your own produce as well as produce aggregated from other enterprises through your shopfront on the Open Food Network.
%p Producer Hubs can take many forms, whether they be a CSA, a veggie-box program, or a food co-op with a rooftop garden.
%p The Open Food Network aims to support as many hub models as possible, so no matter your situation, we want to provide the tools you need to run your organisation or local food business.
.info{ ng: { switch: { default: true } } }
%h3
Please Choose a Package
%i.icon-arrow-right
%p
%strong Your producer enterprise will not be fully activated until a package is selected from the options on the left.
%p
Click on an option to see more detailed information about each package, and hit the red SAVE button when you are done!
.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 Profile Only
%p Get a listing
.bottom ALWAYS FREE
%a.button.selector.hub{ ng: { click: "enterprise.owned && (enterprise.sells='any')", class: "{selected: enterprise.sells=='any', disabled: !enterprise.owned}" } }
.top
%h3 Hub Shop
%p Sell produce from others
.bottom
\2% OF SALES
%br
CAPPED AT $50 PER MONTH
%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 Profile Only
%p Get a listing
.bottom ALWAYS FREE
%a.button.selector.producer-shop{ ng: { click: "enterprise.owned && (enterprise.sells='own')", class: "{selected: enterprise.sells=='own', disabled: !enterprise.owned}" } }
.top
%h3 Producer Shop
%p Sell your own produce
.bottom
\2% OF SALES
%br
CAPPED AT $50 PER MONTH
%a.button.selector.producer-hub{ ng: { click: "enterprise.owned && (enterprise.sells='any')", class: "{selected: enterprise.sells=='any', disabled: !enterprise.owned}" } }
.top
%h3 Producer Hub
%p Sell produce from self and others
.bottom
\2% OF SALES
%br
CAPPED AT $50 PER MONTH
%a.button.update.fullwidth{ ng: { show: "enterprise.owned", class: "{disabled: saved() && !saving, saving: saving}", click: "save()" } }
%span{ ng: {hide: "saved() || saving" } }
SAVE
%i.icon-save
%span{ ng: {show: "saved() && !saving" } }
SAVED
%i.icon-ok-sign
%span{ ng: {show: "saving" } }
SAVING
%i.icon-refresh

View File

@@ -0,0 +1,39 @@
.row.enterprise_producer_panel{ ng: { controller: 'indexProducerPanelCtrl' } }
.alpha.eight.columns
.info{ ng: { show: "enterprise.is_primary_producer==true" } }
%h3 Producer
%p Producers make yummy things to eat &amp;/or drink. You're a producer if you grow it, raise it, brew it, bake it, ferment it, milk it or mould it.
%p Producers can also perform other functions, such as aggregating food from other enterprises and selling it through a shop on the Open Food Network.
.info{ ng: { show: "enterprise.is_primary_producer==false" } }
%h3 Non-Producer
%p Non-producers do not produce any food themselves, meaning that they cannot create their own products for sale through the Open Food Network.
%p Instead, non-producers specialise in linking producers to the end eater, whether it be by aggregating, grading, packing, selling or delivering food.
.omega.eight.columns
%a.button.selector.producer{ ng: { click: 'enterprise.owned && changeToProducer()', class: "{selected: enterprise.is_primary_producer==true, disabled: !enterprise.owned}" } }
.top
%h3 PRODUCER
%p Producers of food
.bottom eg. GROWERS, BAKERS, BREWERS, MAKERS
%a.button.selector.non-producer{ ng: { click: 'enterprise.owned && changeToNonProducer()', class: "{selected: enterprise.is_primary_producer==false, disabled: !enterprise.owned}" } }
.top
%h3 Non-Producer
%p All other food enterprises
.bottom eg. Grocery stores, Food co-ops, Buying groups
%a.button.update.fullwidth{ ng: { show: "enterprise.owned", class: "{disabled: saved() && !saving, saving: saving}", click: "save()" } }
%span{ ng: {hide: "saved() || saving" } }
SAVE
%i.icon-save
%span{ ng: {show: "saved() && !saving" } }
SAVED
%i.icon-ok-sign
%span{ ng: {show: "saving" } }
SAVING
%i.icon-refresh

View File

@@ -0,0 +1,29 @@
.row.enterprise_status_panel{ ng: { controller: 'indexStatusPanelCtrl' } }
.alpha.omega.sixteen.columns
%h4.status-ok.text-center{ ng: { show: "issues.length == 0 && warnings.length == 0" } }
%i.icon-ok-sign
{{ object.name }} is set up and ready to go!
%table{ ng: { show: "issues.length > 0 || warnings.length > 0" } }
%thead
%th.severity
Severity
%th.description
Description
%th.resolve
Resolve
%tr{ ng: { repeat: "issue in issues"} }
%td.severity
%i.icon-warning-sign.issue
%td.description
%span{ bo: { bind: "issue.description" } }
%td.resolve
%div{ ng: { bind: { html: "issue.link" } } }
%tr{ ng: { repeat: "warning in warnings"} }
%td.severity
%i.icon-warning-sign.warning
%td.description
%span{ bo: { bind: "warning.description" } }
%td.resolve
%div{ ng: { bind: { html: "warning.link" } } }

View File

@@ -1,4 +1,4 @@
%div{bindonce:true, style: "display: inline-block" }
%ul{ bindonce: true }
%active-selector{ ng: { repeat: "selector in allSelectors", show: "ifDefined(selector.fits, true)" } }
%render-svg{path: "{{selector.object.icon}}", ng: { if: "selector.object.icon"} }
%span{"bo-text" => "selector.object.name"}

View File

@@ -9,12 +9,10 @@
%br
.filter-shopfront.taxon-selectors.inline-block
%ul
%filter-selector{ objects: "[product] | taxonsOf" }
%filter-selector{ objects: "[product] | taxonsOf" }
.filter-shopfront.property-selectors.inline-block
%ul
%filter-selector{ objects: "[product] | propertiesWithValuesOf" }
%filter-selector{ objects: "[product] | propertiesWithValuesOf" }
%div{"ng-if" => "product.description"}
%hr

View File

@@ -14,7 +14,7 @@
.small-12.columns
.alert-box.info{ "ofn-inline-alert" => true, ng: { show: "visible" } }
%h6 Success! {{ enterprise.name }} added to the Open Food Network
%span If you exit the wizard at any stage, login and go to admin to edit or update your enterprise details.
%span If you exit this wizard at any stage, you need to click the confirmation link in the email you have received. This will take you to your admin interface where you can continue setting up your profile.
%a.close{ ng: { click: "close()" } } &times;
.small-12.large-8.columns

View File

@@ -18,7 +18,7 @@
%p
We've sent a confirmation email to
%strong {{ enterprise.email }}.
%strong {{ enterprise.email }} if it hasn't been activated before.
%br Please follow the instructions there to make your enterprise visible on the Open Food Network.
%a.button.primary{ type: "button", href: "/" } Open Food Network home &gt;

View File

@@ -5,7 +5,7 @@
%h4
%small
%i.ofn-i_040-hub
Create your enterprise profile
You can now create a profile for your Producer or Hub
.hide-for-large-up
%hr
%input.button.small.primary{ type: "button", value: "Let's get started!", ng: { click: "select('details')" } }
@@ -38,6 +38,7 @@
%strong contact
you on the Open Food Network.
%p Use this space to tell the story of your enterprise, to help drive connections to your social and online presence.
%p It's also the first step towards trading on the Open Food Network, or opening an online store.
.row.show-for-large-up
.small-12.columns

View File

@@ -38,9 +38,13 @@
%i.ofn-i_013-help
&nbsp;
%p Producers make yummy things to eat &amp;/or drink. You're a producer if you grow it, raise it, brew it, bake it, ferment it, milk it or mould it.
/ %p Hubs connect the producer to the eater. Hubs can be co-ops, independent retailers, buying groups, wholesalers, CSA box schemes, farm-gate stalls, etc.
.panel.callout
.left
%i.ofn-i_013-help
&nbsp;
%p If youre not a producer, youre probably someone who sells and distributes food. You might be a hub, coop, buying group, retailer, wholesaler or other.
.row.buttons
.small-12.columns
%input.button.secondary{ type: "button", value: "Back", ng: { click: "select('contact')" } }
%input.button.primary.right{ type: "submit", value: "Continue" }
%input.button.primary.right{ type: "submit", value: "Create Profile" }

View File

@@ -1,8 +1,8 @@
%ul
-# In order for the single-line-selector scope to have access to the available selectors,
%filter-selector{objects: "objects()", "active-selectors" => "activeSelectors", "all-selectors" => "allSelectors" }
-# In order for the single-line-selector scope to have access to the available selectors,
%filter-selector{objects: "objects()", "active-selectors" => "activeSelectors", "all-selectors" => "allSelectors" }
%li.more{ ng: { show: "overFlowSelectors().length > 0 || fitting" } }
%ul{ ng: { if: "overFlowSelectors().length > 0 || fitting" } }
%li.more
%a.dropdown{ data: { dropdown: "{{ 'show-more-' + selectorName }}" }, ng: { class: "{active: selectedOverFlowSelectors().length > 0}" } }
%span
+ {{ overFlowSelectors().length }} more

View File

@@ -10,6 +10,7 @@
*= require shared/jquery-ui-timepicker-addon
*= require shared/textAngular.min
*= require shared/ng-tags-input.min
*= require_self
*= require_tree .

View File

@@ -0,0 +1,113 @@
.enterprise_package_panel, .enterprise_producer_panel {
.info {
p {
font-size: 1rem;
margin: 10px 0px;
}
}
a.update {
cursor: pointer;
margin-bottom: 10px;
font-size: 1.3rem;
background-color: #DA5354;
&:hover {
background-color: #CD4E4F;
}
&.disabled {
background-color: #C1C1C1;
}
&.saving {
background-color: #FF9848;
i.icon-refresh {
-webkit-animation: spin 2s infinite linear;
animation: spin 2s infinite linear;
}
}
span{
i{
font-size: 1.5rem;
margin-left: 10px;
}
}
}
a.selector {
display: block;
position: relative;
margin-bottom: 20px;
border: 2px solid black;
text-align: center;
// width: 100%;
cursor: pointer;
&, & * {
color: white;
}
&:hover {
&:after {
border-top-color: #9fc820;
}
}
&.disabled{
background-color: #C1C1C1;
}
.bottom {
background: repeating-linear-gradient(60deg, rgba(84, 152, 218, 0), rgba(84, 152, 218, 0) 5px, rgba(255, 255, 255, 0.25) 5px, rgba(255, 255, 255, 0.25) 10px);
margin-top: 1em;
margin-left: -15px;
margin-right: -15px;
padding: 5px;
text-transform: uppercase;
}
&.selected {
background-color: #000000;
&:after {
top: 50%;
left: 0;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
border-right: 20px solid #000000;
margin-top: -20px;
margin-left: -20px;
}
}
}
}
.enterprise_status_panel {
.status-ok {
margin: 30px 0px;
i.icon-ok-sign {
color: #9fc820;
font-size: 1.5rem;
}
}
td.description{
font-size: 0.9rem;
}
td.severity {
text-align: center;
i {
font-size: 1.5rem;
&.issue{
color: #da5354;
}
&.warning{
color: #ff9848;
}
}
}
}

View File

@@ -0,0 +1,130 @@
tr.panel-toggle-row {
td.panel-toggle{
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
position: relative;
i.icon-chevron::before {
font-size: 1.2rem;
content: "\f078";
}
&.error::before {
font-family: FontAwesome;
font-weight: normal;
font-style: normal;
display: inline-block;
text-decoration: inherit;
position: absolute;
top: 5px;
right: 5px;
font-size: 2rem;
-webkit-font-smoothing: antialiased;
content: "\f071";
color: #da5354;
}
&.status {
i.icon-status::before {
font-size: 1.5rem;
opacity: 0.5;
}
i.issue::before {
content: "\f071";
color: #da5354;
}
i.warning::before {
content: "\f071";
color: #ff9848;
}
i.ok::before {
content: "\f058";
color: #9fc820;
}
}
&:hover {
cursor: pointer;
background-color: #d0e2f6;
* {
color: #1b3c56;
}
i.icon-status::before {
opacity: 1.0;
}
}
}
&.expanded{
td {
border-bottom: 2px solid #444444;
&.selected {
background-color: #ffffff;
border-left: 2px solid #444444;
border-right: 2px solid #444444;
border-top: 2px solid #444444;
border-bottom: none;
&:hover {
background-color: #ffffff;
}
* {
color: #1b3c56;
}
i.icon-status::before {
opacity: 1.0;
}
i.icon-chevron::before {
content: "\f077";
}
}
}
}
}
tr.panel-row {
display: none;
&:hover {
td {
background-color: #ffffff;
}
}
>td {
border-color: #444444;
padding: 0;
.panel {
border-left: 1px solid #444444;
border-right: 1px solid #444444;
border-bottom: 1px solid #444444;
.row{
margin: 0px -4px;
padding: 20px 0px;
.column.alpha, .columns.alpha {
padding-left: 20px;
}
.column.omega, .columns.omega {
padding-right: 20px;
}
}
}
}
}

View File

@@ -249,3 +249,18 @@ span.required {
color: red;
font-size: 110%;
}
table td.actions {
.icon-trash, .icon-edit, icon-copy {
&.disabled {
border-color: #d0d0d0;
color: #c0c0c0;
background-color: #fafafa;
&:hover {
border-color: #a5a5a5;
color: #a5a5a5;
background-color: #fafafa;
}
}
}
}

View File

@@ -8,16 +8,22 @@
}
}
input.update-pending {
border: solid 1px orange;
input, div {
&.update-pending {
border: solid 1px orange;
}
}
input.update-error {
border: solid 1px red;
input, div {
&.update-error {
border: solid 1px red;
}
}
input.update-success {
border: solid 1px #9fc820;
input, div {
&.update-success {
border: solid 1px #9fc820;
}
}
.no-close .ui-dialog-titlebar-close {
@@ -42,4 +48,4 @@ div#group_buy_calculation {
.row span {
text-align: center;
}
}
}

View File

@@ -92,24 +92,23 @@
span.filter-label
opacity: 0.75
.filter-shopfront.taxon-selectors, .filter-shopfront.property-selectors
background: transparent
single-line-selectors
overflow-x: hidden
white-space: nowrap
.f-dropdown
overflow-x: auto
white-space: normal
ul
margin: 0
ul, ul li
list-style: none
.filter-shopfront
&.taxon-selectors, &.property-selectors
background: transparent
single-line-selectors
overflow-x: hidden
white-space: nowrap
.f-dropdown
overflow-x: auto
white-space: normal
ul
margin: 0
display: inline-block
ul, ul li
list-style: none
// Shopfront taxons
&.taxon-selectors

View File

@@ -30,9 +30,18 @@
float: right
margin-left: 0.5rem
//Hub Link
@media all and (max-width: 640px)
a.hub
display: block
//Hub Name
span.hub-name-listing
font-weight: 700
&:after
content: ">>"
display: inline-block
margin-left: 5px
//CLOSED row
&.closed
@@ -65,6 +74,24 @@
.active_table_row:nth-child(2)
padding-bottom: 0.75rem
.producers-list
li.more-producers-link
.less
display: none
a:hover
text-decoration: underline
li.additional-producer
display: none
&.show-more-producers
li.additional-producer
display: block
li.more-producers-link
.more
display: none
.less
display: block
//CURRENT hub (shows selected hub)
&.current
//overwrites active_table
@@ -83,6 +110,7 @@
.active_table_row:first-child .skinny-head
background-color: rgba(255,255,255,0.85)
//INACTIVE - closed hub
&.inactive
&.closed, &.open

View File

@@ -0,0 +1 @@
tags-input{display:block}tags-input *,tags-input :after,tags-input :before{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}tags-input .host{position:relative;margin-top:5px;margin-bottom:5px;height:100%}tags-input .host:active{outline:0}tags-input .tags{-moz-appearance:textfield;-webkit-appearance:textfield;padding:1px;overflow:hidden;word-wrap:break-word;cursor:text;background-color:#fff;border:1px solid #a9a9a9;box-shadow:1px 1px 1px 0 #d3d3d3 inset;height:100%}tags-input .tags.focused{outline:0;-webkit-box-shadow:0 0 3px 1px rgba(5,139,242,.6);-moz-box-shadow:0 0 3px 1px rgba(5,139,242,.6);box-shadow:0 0 3px 1px rgba(5,139,242,.6)}tags-input .tags .tag-list{margin:0;padding:0;list-style-type:none}tags-input .tags .tag-item{margin:2px;padding:0 5px;display:inline-block;float:left;font:14px "Helvetica Neue",Helvetica,Arial,sans-serif;height:26px;line-height:25px;border:1px solid #acacac;border-radius:3px;background:-webkit-linear-gradient(top,#f0f9ff 0,#cbebff 47%,#a1dbff 100%);background:linear-gradient(to bottom,#f0f9ff 0,#cbebff 47%,#a1dbff 100%)}tags-input .tags .tag-item.selected{background:-webkit-linear-gradient(top,#febbbb 0,#fe9090 45%,#ff5c5c 100%);background:linear-gradient(to bottom,#febbbb 0,#fe9090 45%,#ff5c5c 100%)}tags-input .tags .tag-item .remove-button{margin:0 0 0 5px;padding:0;border:none;background:0 0;cursor:pointer;vertical-align:middle;font:700 16px Arial,sans-serif;color:#585858}tags-input .tags .tag-item .remove-button:active{color:red}tags-input .tags .input{border:0;outline:0;margin:2px;padding:0;padding-left:5px;float:left;height:26px;font:14px "Helvetica Neue",Helvetica,Arial,sans-serif}tags-input .tags .input.invalid-tag{color:red}tags-input .tags .input::-ms-clear{display:none}tags-input.ng-invalid .tags{-webkit-box-shadow:0 0 3px 1px rgba(255,0,0,.6);-moz-box-shadow:0 0 3px 1px rgba(255,0,0,.6);box-shadow:0 0 3px 1px rgba(255,0,0,.6)}tags-input[disabled] .host:focus{outline:0}tags-input[disabled] .tags{background-color:#eee;cursor:default}tags-input[disabled] .tags .tag-item{opacity:.65;background:-webkit-linear-gradient(top,#f0f9ff 0,rgba(203,235,255,.75)47%,rgba(161,219,255,.62)100%);background:linear-gradient(to bottom,#f0f9ff 0,rgba(203,235,255,.75)47%,rgba(161,219,255,.62)100%)}tags-input[disabled] .tags .tag-item .remove-button{cursor:default}tags-input[disabled] .tags .tag-item .remove-button:active{color:#585858}tags-input[disabled] .tags .input{background-color:#eee;cursor:default}tags-input .autocomplete{margin-top:5px;position:absolute;padding:5px 0;z-index:999;width:100%;background-color:#fff;border:1px solid rgba(0,0,0,.2);-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}tags-input .autocomplete .suggestion-list{margin:0;padding:0;list-style-type:none;max-height:280px;overflow-y:auto;position:relative}tags-input .autocomplete .suggestion-item{padding:5px 10px;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font:16px "Helvetica Neue",Helvetica,Arial,sans-serif;color:#000;background-color:#fff}tags-input .autocomplete .suggestion-item.selected,tags-input .autocomplete .suggestion-item.selected em{color:#fff;background-color:#0097cf}tags-input .autocomplete .suggestion-item em{font:normal bold 16px "Helvetica Neue",Helvetica,Arial,sans-serif;color:#000;background-color:#fff}

View File

@@ -0,0 +1,29 @@
module Admin
class CustomersController < ResourceController
before_filter :load_managed_shops, only: :index, if: :html_request?
respond_to :json
def index
respond_to do |format|
format.html
format.json do
render json: ActiveModel::ArraySerializer.new( @collection,
each_serializer: Api::Admin::CustomerSerializer, spree_current_user: spree_current_user
).to_json
end
end
end
private
def collection
return Customer.where("1=0") unless json_request? && params[:enterprise_id].present?
enterprise = Enterprise.managed_by(spree_current_user).find_by_id(params[:enterprise_id])
Customer.of(enterprise)
end
def load_managed_shops
@shops = Enterprise.managed_by(spree_current_user).is_distributor
end
end
end

View File

@@ -9,7 +9,7 @@ module Admin
def move_up
EnterpriseGroup.with_isolation_level_serializable do
@enterprise_group = EnterpriseGroup.find params[:enterprise_group_id]
@enterprise_group = EnterpriseGroup.find_by_permalink params[:enterprise_group_id]
@enterprise_group.move_higher
end
redirect_to main_app.admin_enterprise_groups_path
@@ -17,7 +17,7 @@ module Admin
def move_down
EnterpriseGroup.with_isolation_level_serializable do
@enterprise_group = EnterpriseGroup.find params[:enterprise_group_id]
@enterprise_group = EnterpriseGroup.find_by_permalink params[:enterprise_group_id]
@enterprise_group.move_lower
end
redirect_to main_app.admin_enterprise_groups_path
@@ -33,6 +33,12 @@ module Admin
end
alias_method_chain :build_resource, :address
# Overriding method on Spree's resource controller,
# so that resources are found using permalink
def find_resource
EnterpriseGroup.find_by_permalink(params[:id])
end
private
def load_data

View File

@@ -1,8 +1,11 @@
require 'open_food_network/referer_parser'
module Admin
class EnterprisesController < ResourceController
before_filter :load_enterprise_set, :only => :index
before_filter :load_countries, :except => [:index, :set_sells, :check_permalink]
before_filter :load_countries, :except => [:index, :register, :check_permalink]
before_filter :load_methods_and_fees, :only => [:new, :edit, :update, :create]
before_filter :load_groups, :only => [:new, :edit, :update, :create]
before_filter :load_taxons, :only => [:new, :edit, :update, :create]
before_filter :check_can_change_sells, only: :update
before_filter :check_can_change_bulk_sells, only: :bulk_update
@@ -15,34 +18,61 @@ module Admin
before_filter :load_properties, only: [:edit, :update]
before_filter :setup_property, only: [:edit]
helper 'spree/products'
include ActionView::Helpers::TextHelper
include OrderCyclesHelper
def set_sells
enterprise = Enterprise.find_by_permalink(params[:id]) || Enterprise.find(params[:id])
attributes = { sells: params[:sells] }
attributes[:producer_profile_only] = params[:sells] == "none" && !!params[:producer_profile_only]
attributes[:shop_trial_start_date] = Time.now if params[:sells] == "own"
def index
respond_to do |format|
format.html
format.json do
render json: @collection, each_serializer: Api::Admin::IndexEnterpriseSerializer, spree_current_user: spree_current_user
end
end
end
if %w(none own).include?(params[:sells])
if params[:sells] == 'own' && enterprise.shop_trial_start_date
expiry = enterprise.shop_trial_start_date + Enterprise::SHOP_TRIAL_LENGTH.days
if Time.now > expiry
flash[:error] = "Sorry, but you've already had a trial. Expired on: #{expiry.strftime('%Y-%m-%d')}"
else
attributes.delete :shop_trial_start_date
enterprise.update_attributes(attributes)
flash[:notice] = "Welcome back! Your trial expires on: #{expiry.strftime('%Y-%m-%d')}"
end
elsif enterprise.update_attributes(attributes)
flash[:success] = "Congratulations! Registration for #{enterprise.name} is complete!"
def welcome
render layout: "spree/layouts/bare_admin"
end
def update
invoke_callbacks(:update, :before)
if @object.update_attributes(params[object_name])
invoke_callbacks(:update, :after)
flash[:success] = flash_message_for(@object, :successfully_updated)
respond_with(@object) do |format|
format.html { redirect_to location_after_save }
format.js { render :layout => false }
format.json { render json: @object, serializer: Api::Admin::IndexEnterpriseSerializer, spree_current_user: spree_current_user }
end
else
flash[:error] = "Unauthorised"
invoke_callbacks(:update, :fails)
respond_with(@object) do |format|
format.json { render json: { errors: @object.errors.messages }, status: :unprocessable_entity }
end
end
end
def register
if params[:sells] == 'unspecified'
flash[:error] = "Please select a package"
return render :welcome, layout: "spree/layouts/bare_admin"
end
attributes = { sells: params[:sells], visible: true }
if ['own', 'any'].include? params[:sells]
attributes[:shop_trial_start_date] = @enterprise.shop_trial_start_date || Time.now
end
if @enterprise.update_attributes(attributes)
flash[:success] = "Congratulations! Registration for #{@enterprise.name} is complete!"
redirect_to admin_path
else
flash[:error] = "Could not complete registration for #{@enterprise.name}"
render :welcome, layout: "spree/layouts/bare_admin"
end
redirect_to admin_path
end
def bulk_update
@@ -95,7 +125,7 @@ module Admin
private
def load_enterprise_set
@enterprise_set = EnterpriseSet.new collection
@enterprise_set = EnterpriseSet.new(collection) if spree_current_user.admin?
end
def load_countries
@@ -109,6 +139,16 @@ module Admin
coordinator = Enterprise.find_by_id(params[:coordinator_id]) if params[:coordinator_id]
order_cycle = OrderCycle.new(coordinator: coordinator) if order_cycle.nil? && coordinator.present?
return OpenFoodNetwork::OrderCyclePermissions.new(spree_current_user, order_cycle).visible_enterprises
when :index
if spree_current_user.admin?
OpenFoodNetwork::Permissions.new(spree_current_user).
editable_enterprises.
order('is_primary_producer ASC, name')
elsif json_request?
OpenFoodNetwork::Permissions.new(spree_current_user).editable_enterprises
else
Enterprise.where("1=0") unless json_request?
end
else
# TODO was ordered with is_distributor DESC as well, not sure why or how we want to sort this now
OpenFoodNetwork::Permissions.new(spree_current_user).
@@ -127,6 +167,10 @@ module Admin
@enterprise_fees = EnterpriseFee.managed_by(spree_current_user).for_enterprise(@enterprise).order(:fee_type, :name).all
end
def load_groups
@groups = EnterpriseGroup.managed_by(spree_current_user) | @enterprise.groups
end
def load_taxons
@taxons = Spree::Taxon.order(:name)
end
@@ -134,13 +178,15 @@ module Admin
def check_can_change_bulk_sells
unless spree_current_user.admin?
params[:enterprise_set][:collection_attributes].each do |i, enterprise_params|
enterprise_params.delete :sells
enterprise_params.delete :sells unless spree_current_user == Enterprise.find_by_id(enterprise_params[:id]).owner
end
end
end
def check_can_change_sells
params[:enterprise].delete :sells unless spree_current_user.admin?
unless spree_current_user.admin? || spree_current_user == @enterprise.owner
params[:enterprise].delete :sells
end
end
def override_owner
@@ -194,7 +240,8 @@ module Admin
# Overriding method on Spree's resource controller
def location_after_save
refered_from_edit = URI(request.referer).path == main_app.edit_admin_enterprise_path(@enterprise)
referer_path = OpenFoodNetwork::RefererParser::path(request.referer)
refered_from_edit = referer_path == main_app.edit_admin_enterprise_path(@enterprise)
if params[:enterprise].key?(:producer_properties_attributes) && !refered_from_edit
main_app.admin_enterprises_path
else

View File

@@ -1,3 +1,5 @@
require 'open_food_network/referer_parser'
class ApplicationController < ActionController::Base
protect_from_forgery
@@ -9,7 +11,8 @@ class ApplicationController < ActionController::Base
end
def set_checkout_redirect
if request.referer and referer_path = URI(request.referer).path
referer_path = OpenFoodNetwork::RefererParser::path(request.referer)
if referer_path
session["spree_user_return_to"] = [main_app.checkout_path].include?(referer_path) ? referer_path : root_path
end
end

View File

@@ -12,9 +12,6 @@ class BaseController < ApplicationController
before_filter :check_order_cycle_expiry
def load_active_distributors
@active_distributors ||= Enterprise.distributors_with_active_order_cycles
end
private

View File

@@ -12,9 +12,6 @@ class CheckoutController < Spree::CheckoutController
include EnterprisesHelper
def edit
# Because this controller doesn't inherit from our BaseController
# We need to duplicate the code here
@active_distributors ||= Enterprise.distributors_with_active_order_cycles
end
def update

View File

@@ -40,7 +40,7 @@ class EnterpriseConfirmationsController < DeviseController
def new_user_reset_path(resource)
password = Devise.friendly_token.first(8)
user = Spree::User.create(email: resource.email, password: password, password_confirmation: password)
user.send_reset_password_instructions
user.send_reset_password_instructions_without_delay
resource.users << user
spree.edit_spree_user_password_path(user, :reset_password_token => user.reset_password_token, return_to: spree.admin_path)
end

View File

@@ -4,7 +4,7 @@ class EnterprisesController < BaseController
include OrderCyclesHelper
# These prepended filters are in the reverse order of execution
prepend_before_filter :load_active_distributors, :set_order_cycles, :require_distributor_chosen, :reset_order, only: :shop
prepend_before_filter :set_order_cycles, :require_distributor_chosen, :reset_order, only: :shop
before_filter :clean_permalink, only: :check_permalink
respond_to :js, only: :permalink_checker

View File

@@ -1,12 +1,11 @@
class GroupsController < BaseController
layout 'darkswarm'
before_filter :load_active_distributors
def index
@groups = EnterpriseGroup.on_front_page.by_position
end
def show
@group = EnterpriseGroup.find params[:id]
@group = EnterpriseGroup.find_by_permalink(params[:id]) || EnterpriseGroup.find(params[:id])
end
end

View File

@@ -1,11 +1,9 @@
class HomeController < BaseController
layout 'darkswarm'
before_filter :load_active_distributors
def index
end
def about_us
end
end

View File

@@ -1,6 +1,5 @@
class MapController < BaseController
layout 'darkswarm'
before_filter :load_active_distributors
def index
end

View File

@@ -1,7 +1,6 @@
class ProducersController < BaseController
layout 'darkswarm'
before_filter :load_active_distributors
def index
end
end

View File

@@ -10,12 +10,20 @@ class ShopController < BaseController
end
def products
# Can we make this query less slow?
#
if @products = products_for_shop
enterprise_fee_calculator = OpenFoodNetwork::EnterpriseFeeCalculator.new current_distributor, current_order_cycle
render status: 200,
json: ActiveModel::ArraySerializer.new(@products, each_serializer: Api::ProductSerializer,
current_order_cycle: current_order_cycle, current_distributor: current_distributor).to_json
json: ActiveModel::ArraySerializer.new(@products,
each_serializer: Api::ProductSerializer,
current_order_cycle: current_order_cycle,
current_distributor: current_distributor,
variants: variants_for_shop_by_id,
master_variants: master_variants_for_shop_by_id,
enterprise_fee_calculator: enterprise_fee_calculator,
).to_json
else
render json: "", status: 404
end
@@ -56,4 +64,30 @@ class ShopController < BaseController
"name ASC"
end
end
def all_variants_for_shop
# We use the in_stock? method here instead of the in_stock scope because we need to
# look up the stock as overridden by VariantOverrides, and the scope method is not affected
# by them.
Spree::Variant.
for_distribution(current_order_cycle, current_distributor).
each { |v| v.scope_to_hub current_distributor }.
select(&:in_stock?)
end
def variants_for_shop_by_id
index_by_product_id all_variants_for_shop.reject(&:is_master)
end
def master_variants_for_shop_by_id
index_by_product_id all_variants_for_shop.select(&:is_master)
end
def index_by_product_id(variants)
variants.inject({}) do |vs, v|
vs[v.product_id] ||= []
vs[v.product_id] << v
vs
end
end
end

View File

@@ -58,4 +58,12 @@ Spree::Admin::BaseController.class_eval do
"Until you set these up, customers will not be able to shop at this hub."
end
end
def html_request?
request.format.html?
end
def json_request?
request.format.json?
end
end

View File

@@ -7,7 +7,7 @@ Spree::Admin::OrdersController.class_eval do
# We need to add expections for collection actions other than :index here
# because spree_auth_devise causes load_order to be called, which results
# in an auth failure as the @order object is nil for collection actions
before_filter :check_authorization, :except => :bulk_management
before_filter :check_authorization, except: [:bulk_management, :managed]
# After updating an order, the fees should be updated as well
# Currently, adding or deleting line items does not trigger updating the
@@ -17,12 +17,19 @@ Spree::Admin::OrdersController.class_eval do
after_filter :update_distribution_charge, :only => :update
respond_override :index => { :html =>
{ :success => lambda {
{ :success => lambda {
# Filter orders to only show those distributed by current user (or all for admin user)
@orders = @search.result.includes([:user, :shipments, :payments]).
distributed_by_user(spree_current_user).
page(params[:page]).
per(params[:per_page] || Spree::Config[:orders_per_page])
# Filter orders by distributor
if params[:distributor_ids]
@orders = @orders.where(distributor_id: params[:distributor_ids])
end
if params[:order_cycle_ids]
@orders = @orders.where(order_cycle_id: params[:order_cycle_ids])
end
} } }
# Overwrite to use confirm_email_for_customer instead of confirm_email.
@@ -37,4 +44,10 @@ Spree::Admin::OrdersController.class_eval do
def update_distribution_charge
@order.update_distribution_charge!
end
def managed
permissions = OpenFoodNetwork::Permissions.new(spree_current_user)
@orders = permissions.editable_orders.order(:id).ransack(params[:q]).result.page(params[:page]).per(params[:per_page])
render json: @orders, each_serializer: Api::Admin::OrderSerializer
end
end

View File

@@ -5,16 +5,22 @@ Spree::Admin::OverviewController.class_eval do
@product_count = Spree::Product.active.managed_by(spree_current_user).count
@order_cycle_count = OrderCycle.active.managed_by(spree_current_user).count
unspecified = spree_current_user.owned_enterprises.where(sells: 'unspecified')
outside_referral = !URI(request.referer.to_s).path.match(/^\/admin/)
if OpenFoodNetwork::Permissions.new(spree_current_user).manages_one_enterprise? && !spree_current_user.admin?
@enterprise = @enterprises.first
if @enterprise.sells == "unspecified"
render "welcome", layout: "spree/layouts/bare_admin"
if outside_referral && unspecified.any?
redirect_to main_app.welcome_admin_enterprise_path(@enterprise)
else
render "single_enterprise_dashboard"
end
else
render "multi_enterprise_dashboard"
if outside_referral && unspecified.any?
redirect_to main_app.admin_enterprises_path
else
render "multi_enterprise_dashboard"
end
end
end
end

View File

@@ -1,4 +1,5 @@
require 'open_food_network/spree_api_key_loader'
require 'open_food_network/referer_parser'
Spree::Admin::ProductsController.class_eval do
include OpenFoodNetwork::SpreeApiKeyLoader
@@ -53,7 +54,8 @@ Spree::Admin::ProductsController.class_eval do
protected
def location_after_save
if URI(request.referer).path == '/admin/products/bulk_edit'
referer_path = OpenFoodNetwork::RefererParser::path(request.referer)
if referer_path == '/admin/products/bulk_edit'
bulk_edit_admin_products_url
else
location_after_save_original

View File

@@ -7,6 +7,7 @@ require 'open_food_network/customers_report'
require 'open_food_network/users_and_enterprises_report'
require 'open_food_network/order_cycle_management_report'
require 'open_food_network/sales_tax_report'
require 'open_food_network/xero_invoices_report'
Spree::Admin::ReportsController.class_eval do
@@ -679,7 +680,22 @@ Spree::Admin::ReportsController.class_eval do
render_report(@report.header, @report.table, params[:csv], "users_and_enterprises_#{timestamp}.csv")
end
def render_report (header, table, create_csv, csv_file_name)
def xero_invoices
if request.get?
params[:q] ||= {}
params[:q][:completed_at_gt] = Time.zone.now.beginning_of_month
end
@distributors = Enterprise.is_distributor.managed_by(spree_current_user)
@order_cycles = OrderCycle.active_or_complete.accessible_by(spree_current_user).order('orders_close_at DESC')
@search = Spree::Order.complete.managed_by(spree_current_user).order('id DESC').search(params[:q])
orders = @search.result
@report = OpenFoodNetwork::XeroInvoicesReport.new orders, params
render_report(@report.header, @report.table, params[:csv], "xero_invoices_#{timestamp}.csv")
end
def render_report(header, table, create_csv, csv_file_name)
unless create_csv
render :html => table
else
@@ -716,7 +732,9 @@ Spree::Admin::ReportsController.class_eval do
:sales_total => { :name => "Sales Total", :description => "Sales Total For All Orders" },
:users_and_enterprises => { :name => "Users & Enterprises", :description => "Enterprise Ownership & Status" },
:order_cycle_management => {:name => "Order Cycle Management", :description => ''},
:sales_tax => { :name => "Sales Tax", :description => "Sales Tax For Orders" }
:sales_tax => { :name => "Sales Tax", :description => "Sales Tax For Orders" },
:xero_invoices => { :name => "Xero Invoices", :description => 'Invoices for import into Xero' }
}
# Return only reports the user is authorized to view.
reports.select { |action| can? action, :report }

View File

@@ -4,7 +4,7 @@ Spree::Admin::VariantsController.class_eval do
def search
search_params = { :product_name_cont => params[:q], :sku_cont => params[:q] }
@variants = Spree::Variant.ransack(search_params.merge(:m => 'or')).result
@variants = Spree::Variant.where(is_master: false).ransack(search_params.merge(:m => 'or')).result
if params[:order_cycle_id].present?
order_cycle = OrderCycle.find params[:order_cycle_id]

View File

@@ -0,0 +1,11 @@
Spree::Api::LineItemsController.class_eval do
after_filter :apply_enterprise_fees, only: :update
private
def apply_enterprise_fees
authorize! :read, order
order.update_distribution_charge!
end
end

View File

@@ -4,12 +4,4 @@ Spree::Api::OrdersController.class_eval do
# because Spree's API controller causes authorize_read! to be called, which
# results in an ActiveRecord::NotFound Exception as the order object is not
# defined for collection actions
before_filter :authorize_read!, :except => [:managed]
def managed
authorize! :admin, Spree::Order
authorize! :read, Spree::Order
@orders = Spree::Order.ransack(params[:q]).result.distributed_by_user(current_api_user).page(params[:page]).per(params[:per_page])
respond_with(@orders, default_template: :index)
end
end

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