From e284ad62b2cb43fddb8a925f039c9bf3c68175ed Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Fri, 17 Jun 2016 17:03:47 +1000 Subject: [PATCH 01/23] Inject only relative enterprises into shopfront Other shops displayed in producer modals are lazy loaded when opening their modal. --- .../directives/enterprise_modal.js.coffee | 12 +++++++--- .../darkswarm/services/dereferencer.js.coffee | 6 +++-- .../services/enterprise_resource.js.coffee | 8 +++++++ .../darkswarm/services/enterprises.js.coffee | 24 ++++++++++++++++--- app/controllers/enterprises_controller.rb | 15 ++++++++++-- app/helpers/injection_helper.rb | 4 ++++ app/views/enterprises/shop.html.haml | 2 +- config/routes.rb | 1 + 8 files changed, 61 insertions(+), 11 deletions(-) create mode 100644 app/assets/javascripts/darkswarm/services/enterprise_resource.js.coffee diff --git a/app/assets/javascripts/darkswarm/directives/enterprise_modal.js.coffee b/app/assets/javascripts/darkswarm/directives/enterprise_modal.js.coffee index fa6378afe2..099f2a39e4 100644 --- a/app/assets/javascripts/darkswarm/directives/enterprise_modal.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/enterprise_modal.js.coffee @@ -1,9 +1,15 @@ -Darkswarm.directive "enterpriseModal", ($modal)-> +Darkswarm.directive "enterpriseModal", ($modal, Enterprises, EnterpriseResource) -> restrict: 'E' replace: true template: "" transclude: true - link: (scope, elem, attrs, ctrl)-> - elem.on "click", (ev)=> + link: (scope, elem, attrs, ctrl) -> + elem.on "click", (ev) => ev.stopPropagation() + params = + id: scope.enterprise.id + EnterpriseResource.relatives params, (data) => + Enterprises.addEnterprises data + scope.enterprise = Enterprises.enterprises_by_id[scope.enterprise.id] + Enterprises.dereferenceEnterprise scope.enterprise scope.modalInstance = $modal.open(controller: ctrl, templateUrl: 'enterprise_modal.html', scope: scope) diff --git a/app/assets/javascripts/darkswarm/services/dereferencer.js.coffee b/app/assets/javascripts/darkswarm/services/dereferencer.js.coffee index 2061f95ea1..dbe092b0be 100644 --- a/app/assets/javascripts/darkswarm/services/dereferencer.js.coffee +++ b/app/assets/javascripts/darkswarm/services/dereferencer.js.coffee @@ -1,6 +1,8 @@ Darkswarm.factory 'Dereferencer', -> new class Dereferencer - dereference: (array, data)-> + dereference: (array, data) -> if array for object, i in array - array[i] = data[object.id] + key = undefined + key = object.id if object + array[i] = data[key] diff --git a/app/assets/javascripts/darkswarm/services/enterprise_resource.js.coffee b/app/assets/javascripts/darkswarm/services/enterprise_resource.js.coffee new file mode 100644 index 0000000000..e66ec7c176 --- /dev/null +++ b/app/assets/javascripts/darkswarm/services/enterprise_resource.js.coffee @@ -0,0 +1,8 @@ +Darkswarm.factory 'EnterpriseResource', ($resource) -> + $resource('/enterprise/:id.json', {}, { + 'relatives': + method: 'GET' + url: '/enterprises/:id/relatives.json' + isArray: true + cache: true + }) diff --git a/app/assets/javascripts/darkswarm/services/enterprises.js.coffee b/app/assets/javascripts/darkswarm/services/enterprises.js.coffee index 2dddfbc7ef..b030c6e723 100644 --- a/app/assets/javascripts/darkswarm/services/enterprises.js.coffee +++ b/app/assets/javascripts/darkswarm/services/enterprises.js.coffee @@ -1,4 +1,4 @@ -Darkswarm.factory 'Enterprises', (enterprises, CurrentHub, Taxons, Dereferencer, visibleFilter, Matcher, Geo, $rootScope)-> +Darkswarm.factory 'Enterprises', (enterprises, CurrentHub, Taxons, Dereferencer, visibleFilter, Matcher, Geo, $rootScope) -> new class Enterprises enterprises_by_id: {} constructor: -> @@ -20,14 +20,32 @@ Darkswarm.factory 'Enterprises', (enterprises, CurrentHub, Taxons, Dereferencer, if CurrentHub.hub?.id CurrentHub.hub = @enterprises_by_id[CurrentHub.hub.id] for enterprise in @enterprises - Dereferencer.dereference enterprise.hubs, @enterprises_by_id - Dereferencer.dereference enterprise.producers, @enterprises_by_id + @dereferenceEnterprise enterprise + + dereferenceEnterprise: (enterprise) -> + # keep a backup of enterprise ids + # in case we dereference again after adding more enterprises + if enterprise.hub_references + enterprise.hubs = enterprise.hub_references.slice() + else + enterprise.hub_references = enterprise.hubs.slice() + if enterprise.producer_references + enterprise.producers = enterprise.producer_references.slice() + else + enterprise.producer_references = enterprise.producers.slice() + Dereferencer.dereference enterprise.hubs, @enterprises_by_id + Dereferencer.dereference enterprise.producers, @enterprises_by_id dereferenceTaxons: -> for enterprise in @enterprises Dereferencer.dereference enterprise.taxons, Taxons.taxons_by_id Dereferencer.dereference enterprise.supplied_taxons, Taxons.taxons_by_id + addEnterprises: (new_enterprises) -> + return unless new_enterprises && new_enterprises.length + for enterprise in new_enterprises + @enterprises_by_id[enterprise.id] = enterprise + flagMatching: (query) -> for enterprise in @enterprises enterprise.matches_name_query = if query? && query.length > 0 diff --git a/app/controllers/enterprises_controller.rb b/app/controllers/enterprises_controller.rb index 7f627ec73a..83d7c42f62 100644 --- a/app/controllers/enterprises_controller.rb +++ b/app/controllers/enterprises_controller.rb @@ -1,3 +1,5 @@ +require 'open_food_network/enterprise_injection_data' + class EnterprisesController < BaseController layout "darkswarm" helper Spree::ProductsHelper @@ -11,11 +13,21 @@ class EnterprisesController < BaseController respond_to :js, only: :permalink_checker + def relatives + respond_to do |format| + format.json do + enterprises = Enterprise.find(params[:id]).andand.relatives.activated + render(json: enterprises, + each_serializer: Api::EnterpriseSerializer, + data: OpenFoodNetwork::EnterpriseInjectionData.new) + end + end + end def check_permalink return render text: params[:permalink], status: 409 if Enterprise.find_by_permalink params[:permalink] - path = Rails.application.routes.recognize_path( "/#{ params[:permalink].to_s }" ) + path = Rails.application.routes.recognize_path("/#{params[:permalink].to_s}") if path && path[:controller] == "cms_content" render text: params[:permalink], status: 200 else @@ -23,7 +35,6 @@ class EnterprisesController < BaseController end end - private def clean_permalink diff --git a/app/helpers/injection_helper.rb b/app/helpers/injection_helper.rb index 50b9c93fca..d76f37bf62 100644 --- a/app/helpers/injection_helper.rb +++ b/app/helpers/injection_helper.rb @@ -5,6 +5,10 @@ module InjectionHelper inject_json_ams "enterprises", Enterprise.activated.includes(address: :state).all, Api::EnterpriseSerializer, enterprise_injection_data end + def inject_shop_enterprises + inject_json_ams "enterprises", current_distributor.relatives_including_self.activated.includes(address: :state).all, Api::EnterpriseSerializer, enterprise_injection_data + end + def inject_group_enterprises inject_json_ams "group_enterprises", @group.enterprises.activated.all, Api::EnterpriseSerializer, enterprise_injection_data end diff --git a/app/views/enterprises/shop.html.haml b/app/views/enterprises/shop.html.haml index d635f68164..569009db09 100644 --- a/app/views/enterprises/shop.html.haml +++ b/app/views/enterprises/shop.html.haml @@ -5,7 +5,7 @@ - content_for(:image) do = current_distributor.logo.url -= inject_enterprises += inject_shop_enterprises %shop.darkswarm - content_for :order_cycle_form do diff --git a/config/routes.rb b/config/routes.rb index f1b96de181..cd7c7780c4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -55,6 +55,7 @@ Openfoodnetwork::Application.routes.draw do member do get :shop + get :relatives end end get '/:id/shop', to: 'enterprises#shop', as: 'enterprise_shop' From 08fdc8a5bd6907da7a482009af7870f0e01e3720 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Wed, 29 Jun 2016 12:30:43 +1000 Subject: [PATCH 02/23] Load producers of all or selected order cycles into shop --- .../filters/filter_products.js.coffee | 6 +++--- .../darkswarm/services/dereferencer.js.coffee | 18 +++++++++++++----- .../darkswarm/services/enterprises.js.coffee | 18 +++++++----------- app/helpers/injection_helper.rb | 7 ++++++- app/models/enterprise.rb | 16 ++++++++++++++++ .../consumer/shopping/shopping_spec.rb | 18 +++++++++--------- spec/support/request/shop_workflow.rb | 9 +++++++++ 7 files changed, 63 insertions(+), 29 deletions(-) diff --git a/app/assets/javascripts/darkswarm/filters/filter_products.js.coffee b/app/assets/javascripts/darkswarm/filters/filter_products.js.coffee index c01a941659..f65c8854dc 100644 --- a/app/assets/javascripts/darkswarm/filters/filter_products.js.coffee +++ b/app/assets/javascripts/darkswarm/filters/filter_products.js.coffee @@ -1,7 +1,7 @@ -Darkswarm.filter 'products', (Matcher)-> - (products, text)-> +Darkswarm.filter 'products', (Matcher) -> + (products, text) -> products ||= [] text ?= "" - products.filter (product)=> + products.filter (product) => propertiesToMatch = [product.name, product.supplier.name, product.primary_taxon.name] Matcher.match propertiesToMatch, text diff --git a/app/assets/javascripts/darkswarm/services/dereferencer.js.coffee b/app/assets/javascripts/darkswarm/services/dereferencer.js.coffee index dbe092b0be..40f195c6f5 100644 --- a/app/assets/javascripts/darkswarm/services/dereferencer.js.coffee +++ b/app/assets/javascripts/darkswarm/services/dereferencer.js.coffee @@ -1,8 +1,16 @@ Darkswarm.factory 'Dereferencer', -> new class Dereferencer dereference: (array, data) -> - if array - for object, i in array - key = undefined - key = object.id if object - array[i] = data[key] + @dereference_from(array, array, data) + + dereference_from: (source, target, data) -> + unreferenced = [] + if source && target + for object, i in source + key = if object then object.id else undefined + if data.hasOwnProperty(key) + target[i] = data[key] + else + delete target[i] + unreferenced[i] = source[i] + unreferenced diff --git a/app/assets/javascripts/darkswarm/services/enterprises.js.coffee b/app/assets/javascripts/darkswarm/services/enterprises.js.coffee index b030c6e723..6473b58442 100644 --- a/app/assets/javascripts/darkswarm/services/enterprises.js.coffee +++ b/app/assets/javascripts/darkswarm/services/enterprises.js.coffee @@ -23,18 +23,14 @@ Darkswarm.factory 'Enterprises', (enterprises, CurrentHub, Taxons, Dereferencer, @dereferenceEnterprise enterprise dereferenceEnterprise: (enterprise) -> - # keep a backup of enterprise ids + # keep unreferenced enterprise ids # in case we dereference again after adding more enterprises - if enterprise.hub_references - enterprise.hubs = enterprise.hub_references.slice() - else - enterprise.hub_references = enterprise.hubs.slice() - if enterprise.producer_references - enterprise.producers = enterprise.producer_references.slice() - else - enterprise.producer_references = enterprise.producers.slice() - Dereferencer.dereference enterprise.hubs, @enterprises_by_id - Dereferencer.dereference enterprise.producers, @enterprises_by_id + hubs = enterprise.unreferenced_hubs || enterprise.hubs + enterprise.unreferenced_hubs = + Dereferencer.dereference_from hubs, enterprise.hubs, @enterprises_by_id + producers = enterprise.unreferenced_producers || enterprise.producers + enterprise.unreferenced_producers = + Dereferencer.dereference_from producers, enterprise.producers, @enterprises_by_id dereferenceTaxons: -> for enterprise in @enterprises diff --git a/app/helpers/injection_helper.rb b/app/helpers/injection_helper.rb index d76f37bf62..6432597632 100644 --- a/app/helpers/injection_helper.rb +++ b/app/helpers/injection_helper.rb @@ -6,7 +6,12 @@ module InjectionHelper end def inject_shop_enterprises - inject_json_ams "enterprises", current_distributor.relatives_including_self.activated.includes(address: :state).all, Api::EnterpriseSerializer, enterprise_injection_data + ocs = if current_order_cycle + [current_order_cycle] + else + OrderCycle.not_closed.with_distributor(current_distributor) + end + inject_json_ams "enterprises", current_distributor.relatives_and_oc_producers(ocs).activated.includes(address: :state).all, Api::EnterpriseSerializer, enterprise_injection_data end def inject_group_enterprises diff --git a/app/models/enterprise.rb b/app/models/enterprise.rb index 554529d7f2..eca5a44da2 100644 --- a/app/models/enterprise.rb +++ b/app/models/enterprise.rb @@ -220,6 +220,22 @@ class Enterprise < ActiveRecord::Base ", self.id, self.id) end + def relatives_and_oc_producers(order_cycles) + enterprise_ids = [] + order_cycles.each do |oc| + enterprise_ids += oc.exchanges.incoming.pluck :sender_id + end + Enterprise.where(" + enterprises.id IN + (SELECT child_id FROM enterprise_relationships WHERE enterprise_relationships.parent_id=?) + OR enterprises.id IN + (SELECT parent_id FROM enterprise_relationships WHERE enterprise_relationships.child_id=?) + OR enterprises.id IN + (?) + OR enterprises.id = ? + ", id, id, enterprise_ids, id) + end + def relatives_including_self Enterprise.where(id: relatives.pluck(:id) | [id]) end diff --git a/spec/features/consumer/shopping/shopping_spec.rb b/spec/features/consumer/shopping/shopping_spec.rb index 7dc9f474da..b449b4d083 100644 --- a/spec/features/consumer/shopping/shopping_spec.rb +++ b/spec/features/consumer/shopping/shopping_spec.rb @@ -34,7 +34,7 @@ feature "As a consumer I want to shop with a distributor", js: true do it "shows the producers for a distributor" do exchange = Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id) - exchange.variants << variant + add_variant_to_order_cycle(exchange, variant) visit shop_path find("#tab_producers a").click @@ -68,7 +68,7 @@ feature "As a consumer I want to shop with a distributor", js: true do it "shows products after selecting an order cycle" do variant.update_attribute(:display_name, "kitten") variant.update_attribute(:display_as, "rabbit") - exchange1.variants << variant ## add product to exchange + add_variant_to_order_cycle(exchange1, variant) visit shop_path page.should_not have_content product.name Spree::Order.last.order_cycle.should == nil @@ -89,8 +89,8 @@ feature "As a consumer I want to shop with a distributor", js: true do it "shows the correct fees after selecting and changing an order cycle" do enterprise_fee = create(:enterprise_fee, amount: 1001) exchange2.enterprise_fees << enterprise_fee - exchange2.variants << variant - exchange1.variants << variant + add_variant_to_order_cycle(exchange2, variant) + add_variant_to_order_cycle(exchange1, variant) # -- Selecting an order cycle visit shop_path @@ -116,8 +116,8 @@ feature "As a consumer I want to shop with a distributor", js: true do describe "declining to clear the cart" do before do - exchange2.variants << variant - exchange1.variants << variant + add_variant_to_order_cycle(exchange2, variant) + add_variant_to_order_cycle(exchange1, variant) visit shop_path select "turtles", from: "order_cycle_id" @@ -147,9 +147,9 @@ feature "As a consumer I want to shop with a distributor", js: true do before do exchange.update_attribute :pickup_time, "frogs" - exchange.variants << variant - exchange.variants << variant1 - exchange.variants << variant2 + add_variant_to_order_cycle(exchange, variant) + add_variant_to_order_cycle(exchange, variant1) + add_variant_to_order_cycle(exchange, variant2) order.order_cycle = oc1 end diff --git a/spec/support/request/shop_workflow.rb b/spec/support/request/shop_workflow.rb index 279ead2630..d7654617e1 100644 --- a/spec/support/request/shop_workflow.rb +++ b/spec/support/request/shop_workflow.rb @@ -29,6 +29,15 @@ module ShopWorkflow end def add_variant_to_order_cycle(exchange, variant) + oc = exchange.order_cycle + supplier = variant.product.supplier + # An order cycle needs an incoming exchange for a supplier + # before having its products. Otherwise the data will be inconsistent and + # and not all needed enterprises are loaded into the shop page. + if oc.exchanges.from_enterprise(supplier).incoming.empty? + create(:exchange, order_cycle: oc, incoming: true, + sender: supplier, receiver: oc.coordinator) + end exchange.variants << variant end From c253d73d1195bf501c52c7282b4e8bcb26751075 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Wed, 29 Jun 2016 15:46:51 +1000 Subject: [PATCH 03/23] Refactoring with feedback on pr #1073 --- .../darkswarm/services/dereferencer.js.coffee | 2 +- app/controllers/enterprises_controller.rb | 3 ++- app/models/enterprise.rb | 25 +++++++++---------- spec/support/request/shop_workflow.rb | 23 ++++++++++------- 4 files changed, 29 insertions(+), 24 deletions(-) diff --git a/app/assets/javascripts/darkswarm/services/dereferencer.js.coffee b/app/assets/javascripts/darkswarm/services/dereferencer.js.coffee index 40f195c6f5..b4817e0e2d 100644 --- a/app/assets/javascripts/darkswarm/services/dereferencer.js.coffee +++ b/app/assets/javascripts/darkswarm/services/dereferencer.js.coffee @@ -7,7 +7,7 @@ Darkswarm.factory 'Dereferencer', -> unreferenced = [] if source && target for object, i in source - key = if object then object.id else undefined + key = object?.id if data.hasOwnProperty(key) target[i] = data[key] else diff --git a/app/controllers/enterprises_controller.rb b/app/controllers/enterprises_controller.rb index 83d7c42f62..70d240abd1 100644 --- a/app/controllers/enterprises_controller.rb +++ b/app/controllers/enterprises_controller.rb @@ -16,7 +16,8 @@ class EnterprisesController < BaseController def relatives respond_to do |format| format.json do - enterprises = Enterprise.find(params[:id]).andand.relatives.activated + enterprise = Enterprise.find(params[:id]) + enterprises = enterprise.andand.relatives.andand.activated render(json: enterprises, each_serializer: Api::EnterpriseSerializer, data: OpenFoodNetwork::EnterpriseInjectionData.new) diff --git a/app/models/enterprise.rb b/app/models/enterprise.rb index eca5a44da2..ef11c97e49 100644 --- a/app/models/enterprise.rb +++ b/app/models/enterprise.rb @@ -176,6 +176,16 @@ class Enterprise < ActiveRecord::Base joins(:enterprise_roles).where('enterprise_roles.user_id = ?', user.id) end } + scope :relatives_of_one_union_others, lambda { |one, others| + where(" + enterprises.id IN + (SELECT child_id FROM enterprise_relationships WHERE enterprise_relationships.parent_id=?) + OR enterprises.id IN + (SELECT parent_id FROM enterprise_relationships WHERE enterprise_relationships.child_id=?) + OR enterprises.id IN + (?) + ", one, one, others) + } # Force a distinct count to work around relation count issue https://github.com/rails/rails/issues/5554 def self.distinct_count @@ -221,19 +231,8 @@ class Enterprise < ActiveRecord::Base end def relatives_and_oc_producers(order_cycles) - enterprise_ids = [] - order_cycles.each do |oc| - enterprise_ids += oc.exchanges.incoming.pluck :sender_id - end - Enterprise.where(" - enterprises.id IN - (SELECT child_id FROM enterprise_relationships WHERE enterprise_relationships.parent_id=?) - OR enterprises.id IN - (SELECT parent_id FROM enterprise_relationships WHERE enterprise_relationships.child_id=?) - OR enterprises.id IN - (?) - OR enterprises.id = ? - ", id, id, enterprise_ids, id) + enterprise_ids = Exchange.in_order_cycle(order_cycles).incoming.pluck :sender_id + Enterprise.relatives_of_one_union_others(id, enterprise_ids) end def relatives_including_self diff --git a/spec/support/request/shop_workflow.rb b/spec/support/request/shop_workflow.rb index d7654617e1..01c24bee05 100644 --- a/spec/support/request/shop_workflow.rb +++ b/spec/support/request/shop_workflow.rb @@ -29,19 +29,24 @@ module ShopWorkflow end def add_variant_to_order_cycle(exchange, variant) - oc = exchange.order_cycle - supplier = variant.product.supplier - # An order cycle needs an incoming exchange for a supplier - # before having its products. Otherwise the data will be inconsistent and - # and not all needed enterprises are loaded into the shop page. - if oc.exchanges.from_enterprise(supplier).incoming.empty? - create(:exchange, order_cycle: oc, incoming: true, - sender: supplier, receiver: oc.coordinator) - end + ensure_supplier_exchange(exchange, variant.product.supplier) exchange.variants << variant end def set_order_cycle(order, order_cycle) order.update_attribute(:order_cycle, order_cycle) end + + private + + # An order cycle needs an incoming exchange for a supplier + # before having its products. Otherwise the data will be inconsistent and + # and not all needed enterprises are loaded into the shop page. + def ensure_supplier_exchange(exchange, supplier) + oc = exchange.order_cycle + if oc.exchanges.from_enterprise(supplier).incoming.empty? + create(:exchange, order_cycle: oc, incoming: true, + sender: supplier, receiver: oc.coordinator) + end + end end From 78b22c4a823f6a3db72400c417ec09c442938da4 Mon Sep 17 00:00:00 2001 From: Bing Xie Date: Wed, 22 Jun 2016 14:54:06 +1000 Subject: [PATCH 04/23] Fix incorrectly aligned columns --- .../orders_and_fulfillments_report.rb | 1 + .../orders_and_fulfillments_report_spec.rb | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/lib/open_food_network/orders_and_fulfillments_report.rb b/lib/open_food_network/orders_and_fulfillments_report.rb index 089838a1b1..b4778a12aa 100644 --- a/lib/open_food_network/orders_and_fulfillments_report.rb +++ b/lib/open_food_network/orders_and_fulfillments_report.rb @@ -216,6 +216,7 @@ module OpenFoodNetwork proc { |line_items| "" }, proc { |line_items| "" }, proc { |line_items| "" }, + proc { |line_items| line_items.all? { |li| li.order.paid? } ? "Yes" : "No" }, proc { |line_items| line_items.first.order.shipping_method.andand.name }, proc { |line_items| rsa.call(line_items) ? 'Y' : 'N' }, diff --git a/spec/lib/open_food_network/orders_and_fulfillments_report_spec.rb b/spec/lib/open_food_network/orders_and_fulfillments_report_spec.rb index 55c8bd1197..f37dcefa02 100644 --- a/spec/lib/open_food_network/orders_and_fulfillments_report_spec.rb +++ b/spec/lib/open_food_network/orders_and_fulfillments_report_spec.rb @@ -93,5 +93,24 @@ module OpenFoodNetwork end end end + + describe "columns are aligned" do + let(:d1) { create(:distributor_enterprise) } + let(:oc1) { create(:simple_order_cycle) } + let(:o1) { create(:order, completed_at: 1.day.ago, order_cycle: oc1, distributor: d1) } + let(:li1) { build(:line_item) } + let(:user) { create(:admin_user)} + + before { o1.line_items << li1 } + + it 'has aligned columsn' do + report_types = ["", "order_cycle_supplier_totals", "order_cycle_supplier_totals_by_distributor", "order_cycle_distributor_totals_by_supplier", "order_cycle_customer_totals"] + + report_types.each do |report_type| + report = OrdersAndFulfillmentsReport.new user, report_type: report_type + report.header.size.should == report.columns.size + end + end + end end end From e8b83bef416c58a4f17a6de3819c9ed5996a6fde Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 30 Jun 2016 11:54:59 +1000 Subject: [PATCH 05/23] Simplify responding to search --- .../darkswarm/directives/map_search.js.coffee | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/app/assets/javascripts/darkswarm/directives/map_search.js.coffee b/app/assets/javascripts/darkswarm/directives/map_search.js.coffee index e67ce529a5..3e546b82b3 100644 --- a/app/assets/javascripts/darkswarm/directives/map_search.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/map_search.js.coffee @@ -29,18 +29,11 @@ Darkswarm.directive 'mapSearch', ($timeout)-> google.maps.event.addListener searchBox, "places_changed", -> places = searchBox.getPlaces() - return if places.length is 0 - # For each place, get the icon, place name, and location. - markers = [] - bounds = new google.maps.LatLngBounds() - for place in places - #map.setCenter place.geometry.location + for place in places when place.geometry.viewport? map.fitBounds place.geometry.viewport - #map.fitBounds bounds # Bias the SearchBox results towards places that are within the bounds of the # current map's viewport. google.maps.event.addListener map, "bounds_changed", -> bounds = map.getBounds() searchBox.setBounds bounds - From 54028f4e7ea6d3c8586298b23a361d7c40c7dd7d Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 30 Jun 2016 12:03:48 +1000 Subject: [PATCH 06/23] Split directive into functions --- .../darkswarm/directives/map_search.js.coffee | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/app/assets/javascripts/darkswarm/directives/map_search.js.coffee b/app/assets/javascripts/darkswarm/directives/map_search.js.coffee index 3e546b82b3..cb9dce98b4 100644 --- a/app/assets/javascripts/darkswarm/directives/map_search.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/map_search.js.coffee @@ -1,18 +1,27 @@ -Darkswarm.directive 'mapSearch', ($timeout)-> +Darkswarm.directive 'mapSearch', ($timeout) -> # Install a basic search field in a map restrict: 'E' require: '^googleMap' replace: true template: '' - link: (scope, elem, attrs, ctrl)-> + scope: {} + link: (scope, elem, attrs, ctrl) -> $timeout => map = ctrl.getMap() - # Use OSM tiles server - map.mapTypes.set 'OSM', new (google.maps.ImageMapType)( + # Does this *really* belong here? It's not about search. + scope.useOsmTiles map + + searchBox = scope.createSearchBox map + scope.respondToSearch map, searchBox + scope.biasResults map, searchBox + + + scope.useOsmTiles = (map) -> + map.mapTypes.set 'OSM', new google.maps.ImageMapType getTileUrl: (coord, zoom) -> # "Wrap" x (logitude) at 180th meridian properly - # NB: Don't touch coord.x because coord param is by reference, and changing its x property breakes something in Google's lib + # NB: Don't touch coord.x because coord param is by reference, and changing its x property breaks something in Google's lib tilesPerGlobe = 1 << zoom x = coord.x % tilesPerGlobe if x < 0 @@ -21,19 +30,22 @@ Darkswarm.directive 'mapSearch', ($timeout)-> 'http://tile.openstreetmap.org/' + zoom + '/' + x + '/' + coord.y + '.png' tileSize: new (google.maps.Size)(256, 256) name: 'OpenStreetMap' - maxZoom: 18) + maxZoom: 18 - input = (document.getElementById("pac-input")) + scope.createSearchBox = (map) -> + input = document.getElementById("pac-input") map.controls[google.maps.ControlPosition.TOP_LEFT].push input - searchBox = new google.maps.places.SearchBox((input)) + return new google.maps.places.SearchBox(input) + scope.respondToSearch = (map, searchBox) -> google.maps.event.addListener searchBox, "places_changed", -> places = searchBox.getPlaces() for place in places when place.geometry.viewport? map.fitBounds place.geometry.viewport - # Bias the SearchBox results towards places that are within the bounds of the - # current map's viewport. + # Bias the SearchBox results towards places that are within the bounds of the + # current map's viewport. + scope.biasResults = (map, searchBox) -> google.maps.event.addListener map, "bounds_changed", -> bounds = map.getBounds() searchBox.setBounds bounds From f586dbc3e19acd8b8fbafb832dfb7e3bea8d61a7 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 30 Jun 2016 12:14:47 +1000 Subject: [PATCH 07/23] Extract OSM tile setup to own directive --- .../directives/map_osm_tiles.js.coffee | 21 +++++++++++++++++++ .../darkswarm/directives/map_search.js.coffee | 18 ---------------- app/views/groups/show.html.haml | 1 + app/views/map/index.html.haml | 1 + 4 files changed, 23 insertions(+), 18 deletions(-) create mode 100644 app/assets/javascripts/darkswarm/directives/map_osm_tiles.js.coffee diff --git a/app/assets/javascripts/darkswarm/directives/map_osm_tiles.js.coffee b/app/assets/javascripts/darkswarm/directives/map_osm_tiles.js.coffee new file mode 100644 index 0000000000..9df5fd0d4b --- /dev/null +++ b/app/assets/javascripts/darkswarm/directives/map_osm_tiles.js.coffee @@ -0,0 +1,21 @@ +Darkswarm.directive 'mapOsmTiles', ($timeout) -> + restrict: 'E' + require: '^googleMap' + scope: {} + link: (scope, elem, attrs, ctrl) -> + $timeout => + map = ctrl.getMap() + + map.mapTypes.set 'OSM', new google.maps.ImageMapType + getTileUrl: (coord, zoom) -> + # "Wrap" x (logitude) at 180th meridian properly + # NB: Don't touch coord.x because coord param is by reference, and changing its x property breaks something in Google's lib + tilesPerGlobe = 1 << zoom + x = coord.x % tilesPerGlobe + if x < 0 + x = tilesPerGlobe + x + # Wrap y (latitude) in a like manner if you want to enable vertical infinite scroll + 'http://tile.openstreetmap.org/' + zoom + '/' + x + '/' + coord.y + '.png' + tileSize: new (google.maps.Size)(256, 256) + name: 'OpenStreetMap' + maxZoom: 18 diff --git a/app/assets/javascripts/darkswarm/directives/map_search.js.coffee b/app/assets/javascripts/darkswarm/directives/map_search.js.coffee index cb9dce98b4..6f8aef6dc8 100644 --- a/app/assets/javascripts/darkswarm/directives/map_search.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/map_search.js.coffee @@ -9,29 +9,11 @@ Darkswarm.directive 'mapSearch', ($timeout) -> $timeout => map = ctrl.getMap() - # Does this *really* belong here? It's not about search. - scope.useOsmTiles map - searchBox = scope.createSearchBox map scope.respondToSearch map, searchBox scope.biasResults map, searchBox - scope.useOsmTiles = (map) -> - map.mapTypes.set 'OSM', new google.maps.ImageMapType - getTileUrl: (coord, zoom) -> - # "Wrap" x (logitude) at 180th meridian properly - # NB: Don't touch coord.x because coord param is by reference, and changing its x property breaks something in Google's lib - tilesPerGlobe = 1 << zoom - x = coord.x % tilesPerGlobe - if x < 0 - x = tilesPerGlobe + x - # Wrap y (latitude) in a like manner if you want to enable vertical infinite scroll - 'http://tile.openstreetmap.org/' + zoom + '/' + x + '/' + coord.y + '.png' - tileSize: new (google.maps.Size)(256, 256) - name: 'OpenStreetMap' - maxZoom: 18 - scope.createSearchBox = (map) -> input = document.getElementById("pac-input") map.controls[google.maps.ControlPosition.TOP_LEFT].push input diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index af497a4195..a21bdb7460 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -40,6 +40,7 @@ .map-container %map{"ng-if" => "(isActive(\'/map\') && (mapShowed = true)) || mapShowed"} %google-map{options: "map.additional_options", center: "map.center", zoom: "map.zoom", styles: "map.styles", draggable: "true"} + %map-osm-tiles %map-search %markers{models: "mapMarkers", fit: "true", coords: "'self'", icon: "'icon'", click: "'reveal'"} diff --git a/app/views/map/index.html.haml b/app/views/map/index.html.haml index e4a22e540c..75bb99f9d7 100644 --- a/app/views/map/index.html.haml +++ b/app/views/map/index.html.haml @@ -6,6 +6,7 @@ .map-container{"fill-vertical" => true} %map{"ng-controller" => "MapCtrl"} %google-map{options: "map.additional_options", center: "map.center", zoom: "map.zoom", styles: "map.styles", draggable: "true"} + %map-osm-tiles %map-search %markers{models: "OfnMap.enterprises", fit: "true", coords: "'self'", icon: "'icon'", click: "'reveal'"} From a9a68151ec3f96c00e9f57bfe1b7eae425319897 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 30 Jun 2016 12:15:40 +1000 Subject: [PATCH 08/23] Syntax --- .../javascripts/darkswarm/directives/map_osm_tiles.js.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/darkswarm/directives/map_osm_tiles.js.coffee b/app/assets/javascripts/darkswarm/directives/map_osm_tiles.js.coffee index 9df5fd0d4b..0dcda8f59a 100644 --- a/app/assets/javascripts/darkswarm/directives/map_osm_tiles.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/map_osm_tiles.js.coffee @@ -16,6 +16,6 @@ Darkswarm.directive 'mapOsmTiles', ($timeout) -> x = tilesPerGlobe + x # Wrap y (latitude) in a like manner if you want to enable vertical infinite scroll 'http://tile.openstreetmap.org/' + zoom + '/' + x + '/' + coord.y + '.png' - tileSize: new (google.maps.Size)(256, 256) + tileSize: new google.maps.Size(256, 256) name: 'OpenStreetMap' maxZoom: 18 From e6bdd2303d6b5653b77f274d3bf60cc1df0c6294 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 1 Jul 2016 13:32:14 +1000 Subject: [PATCH 09/23] Extract showing search result --- .../darkswarm/directives/map_search.js.coffee | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/darkswarm/directives/map_search.js.coffee b/app/assets/javascripts/darkswarm/directives/map_search.js.coffee index 6f8aef6dc8..7a3e633384 100644 --- a/app/assets/javascripts/darkswarm/directives/map_search.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/map_search.js.coffee @@ -10,7 +10,7 @@ Darkswarm.directive 'mapSearch', ($timeout) -> map = ctrl.getMap() searchBox = scope.createSearchBox map - scope.respondToSearch map, searchBox + scope.bindSearchResponse map, searchBox scope.biasResults map, searchBox @@ -19,11 +19,16 @@ Darkswarm.directive 'mapSearch', ($timeout) -> map.controls[google.maps.ControlPosition.TOP_LEFT].push input return new google.maps.places.SearchBox(input) - scope.respondToSearch = (map, searchBox) -> - google.maps.event.addListener searchBox, "places_changed", -> - places = searchBox.getPlaces() - for place in places when place.geometry.viewport? - map.fitBounds place.geometry.viewport + scope.bindSearchResponse = (map, searchBox) -> + google.maps.event.addListener searchBox, "places_changed", => + scope.showSearchResult map, searchBox + + scope.showSearchResult = (map, searchBox) -> + places = searchBox.getPlaces() + for place in places when place.geometry.viewport? + map.fitBounds place.geometry.viewport + scope.$apply -> + model.$setViewValue elem.val() # Bias the SearchBox results towards places that are within the bounds of the # current map's viewport. From 34b2f72ae8ecd3cafa80f34e074208103fef2938 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 1 Jul 2016 15:30:55 +1000 Subject: [PATCH 10/23] When query changed (typing or autocomplete), update URL. When page loads, perform query search. --- .../darkswarm/directives/map_search.js.coffee | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/darkswarm/directives/map_search.js.coffee b/app/assets/javascripts/darkswarm/directives/map_search.js.coffee index 7a3e633384..a074539a23 100644 --- a/app/assets/javascripts/darkswarm/directives/map_search.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/map_search.js.coffee @@ -1,23 +1,33 @@ -Darkswarm.directive 'mapSearch', ($timeout) -> +Darkswarm.directive 'mapSearch', ($timeout, Search) -> # Install a basic search field in a map restrict: 'E' - require: '^googleMap' + require: ['^googleMap', 'ngModel'] replace: true - template: '' + template: '' scope: {} - link: (scope, elem, attrs, ctrl) -> + + controller: ($scope) -> + $scope.query = Search.search() + + $scope.$watch 'query', (query) -> + Search.search query + + + link: (scope, elem, attrs, ctrls) -> + [ctrl, model] = ctrls + scope.input = document.getElementById("pac-input") + $timeout => map = ctrl.getMap() searchBox = scope.createSearchBox map scope.bindSearchResponse map, searchBox scope.biasResults map, searchBox - + scope.performUrlSearch map scope.createSearchBox = (map) -> - input = document.getElementById("pac-input") - map.controls[google.maps.ControlPosition.TOP_LEFT].push input - return new google.maps.places.SearchBox(input) + map.controls[google.maps.ControlPosition.TOP_LEFT].push scope.input + return new google.maps.places.SearchBox(scope.input) scope.bindSearchResponse = (map, searchBox) -> google.maps.event.addListener searchBox, "places_changed", => @@ -30,6 +40,12 @@ Darkswarm.directive 'mapSearch', ($timeout) -> scope.$apply -> model.$setViewValue elem.val() + # When the map loads, and we have a search from ?query, perform that search + scope.performUrlSearch = (map) -> + google.maps.event.addListener map, "tilesloaded", => + google.maps.event.trigger(scope.input, 'focus'); + google.maps.event.trigger(scope.input, 'keydown', {keyCode: 13}); + # Bias the SearchBox results towards places that are within the bounds of the # current map's viewport. scope.biasResults = (map, searchBox) -> From d6f21b24dac649b52082cb2ab6b52a6ea710803e Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 6 Jul 2016 11:04:36 +1000 Subject: [PATCH 11/23] Add specs for producers and shops search by URL --- spec/features/consumer/producers_spec.rb | 69 ++++++++++-------- spec/features/consumer/shops_spec.rb | 90 ++++++++++++++---------- 2 files changed, 91 insertions(+), 68 deletions(-) diff --git a/spec/features/consumer/producers_spec.rb b/spec/features/consumer/producers_spec.rb index 634350af18..5c89a23529 100644 --- a/spec/features/consumer/producers_spec.rb +++ b/spec/features/consumer/producers_spec.rb @@ -27,45 +27,54 @@ feature %q{ producer1.set_producer_property 'Local', 'Victoria' producer2.set_producer_property 'Fair Trade', 'FT123' - - visit producers_path end - it "filters by taxon" do - toggle_filters - - toggle_filter 'Vegetables' - - page.should_not have_content producer1.name - page.should have_content producer2.name - - toggle_filter 'Vegetables' - toggle_filter 'Fruit' - - page.should have_content producer1.name - page.should_not have_content producer2.name + it "searches by URL" do + visit producers_path(anchor: "/?query=xyzzy") + expect(page).to have_content "Sorry, no results found for xyzzy" end - it "shows all producers with expandable details" do - page.should have_content producer1.name - expand_active_table_node producer1.name + context "on the producers page" do + before do + visit producers_path + end - # -- Taxons - page.should have_content 'Fruit' + it "filters by taxon" do + toggle_filters - # -- Properties - page.should have_content 'Organic' # Product property - page.should have_content 'Local' # Producer property - end + toggle_filter 'Vegetables' - it "doesn't show invisible producers" do - page.should_not have_content invisible_producer.name - end + page.should_not have_content producer1.name + page.should have_content producer2.name - it "links to places to buy produce" do - expand_active_table_node producer1.name - page.should have_link shop.name + toggle_filter 'Vegetables' + toggle_filter 'Fruit' + + page.should have_content producer1.name + page.should_not have_content producer2.name + end + + it "shows all producers with expandable details" do + page.should have_content producer1.name + expand_active_table_node producer1.name + + # -- Taxons + page.should have_content 'Fruit' + + # -- Properties + page.should have_content 'Organic' # Product property + page.should have_content 'Local' # Producer property + end + + it "doesn't show invisible producers" do + page.should_not have_content invisible_producer.name + end + + it "links to places to buy produce" do + expand_active_table_node producer1.name + page.should have_link shop.name + end end diff --git a/spec/features/consumer/shops_spec.rb b/spec/features/consumer/shops_spec.rb index 8b1a709462..0c5d3d7e09 100644 --- a/spec/features/consumer/shops_spec.rb +++ b/spec/features/consumer/shops_spec.rb @@ -14,56 +14,70 @@ feature 'Shops', js: true do before do producer.set_producer_property 'Organic', 'NASAA 12345' - visit shops_path end - it "shows hubs" do - page.should have_content distributor.name - expand_active_table_node distributor.name - page.should have_content "OUR PRODUCERS" + it "searches by URL" do + visit shops_path(anchor: "/?query=xyzzy") + expect(page).to have_content "Sorry, no results found for xyzzy" end - it "does not show invisible hubs" do - page.should_not have_content invisible_distributor.name - end - it "should not show hubs that are not in an order cycle" do - create(:simple_product, distributors: [d1, d2]) - visit shops_path - page.should have_no_selector 'hub.inactive' - page.should have_no_selector 'hub', text: d2.name - end + context "on the shops path" do + before do + visit shops_path + end - it "should show closed shops after clicking the button" do - create(:simple_product, distributors: [d1, d2]) - visit shops_path - click_link_and_ensure("Show closed shops", -> { page.has_selector? 'hub.inactive' }) - page.should have_selector 'hub.inactive', text: d2.name - end - - it "should link to the hub page" do - follow_active_table_node distributor.name - expect(page).to have_current_path enterprise_shop_path(distributor) - end - - describe "hub producer modal" do - let!(:product) { create(:simple_product, supplier: producer, taxons: [taxon]) } - let!(:taxon) { create(:taxon, name: 'Fruit') } - let!(:order_cycle) { create(:simple_order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise), variants: [product.variants.first]) } - - it "should show hub producer modals" do + it "shows hubs" do + page.should have_content distributor.name expand_active_table_node distributor.name - expect(page).to have_content producer.name - open_enterprise_modal producer - modal_should_be_open_for producer + page.should have_content "OUR PRODUCERS" + end - within ".reveal-modal" do - expect(page).to have_content 'Fruit' # Taxon - expect(page).to have_content 'Organic' # Producer property + it "does not show invisible hubs" do + page.should_not have_content invisible_distributor.name + end + + it "should not show hubs that are not in an order cycle" do + create(:simple_product, distributors: [d1, d2]) + visit shops_path + page.should have_no_selector 'hub.inactive' + page.should have_no_selector 'hub', text: d2.name + end + + it "should show closed shops after clicking the button" do + create(:simple_product, distributors: [d1, d2]) + visit shops_path + click_link_and_ensure("Show closed shops", -> { page.has_selector? 'hub.inactive' }) + page.should have_selector 'hub.inactive', text: d2.name + end + + it "should link to the hub page" do + follow_active_table_node distributor.name + expect(page).to have_current_path enterprise_shop_path(distributor) + end + + describe "hub producer modal" do + let!(:product) { create(:simple_product, supplier: producer, taxons: [taxon]) } + let!(:taxon) { create(:taxon, name: 'Fruit') } + let!(:order_cycle) { create(:simple_order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise), variants: [product.variants.first]) } + + it "should show hub producer modals" do + expand_active_table_node distributor.name + expect(page).to have_content producer.name + open_enterprise_modal producer + modal_should_be_open_for producer + + within ".reveal-modal" do + expect(page).to have_content 'Fruit' # Taxon + expect(page).to have_content 'Organic' # Producer property + end end end end + + private + def click_link_and_ensure(link_text, check) # Buttons appear to be unresponsive for a while, so keep clicking them until content appears using_wait_time 0.5 do From f09cd9e47730dac322fe721e58b45173df0125aa Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 6 Jul 2016 11:04:53 +1000 Subject: [PATCH 12/23] Allow groups to be searched by URL --- .../darkswarm/controllers/groups_controller.js.coffee | 6 +++++- spec/features/consumer/groups_spec.rb | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/darkswarm/controllers/groups_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/groups_controller.js.coffee index 8fd47c49f8..91cbe0bf54 100644 --- a/app/assets/javascripts/darkswarm/controllers/groups_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/groups_controller.js.coffee @@ -1,3 +1,7 @@ -Darkswarm.controller "GroupsCtrl", ($scope, Groups) -> +Darkswarm.controller "GroupsCtrl", ($scope, Groups, Search) -> $scope.Groups = Groups $scope.order = 'position' + $scope.query = Search.search() + + $scope.$watch "query", (query)-> + Search.search query diff --git a/spec/features/consumer/groups_spec.rb b/spec/features/consumer/groups_spec.rb index e51ac39ea2..5ea96ac17e 100644 --- a/spec/features/consumer/groups_spec.rb +++ b/spec/features/consumer/groups_spec.rb @@ -12,8 +12,8 @@ feature 'Groups', js: true do page.should have_content group.name end - it "renders enterprise modals for groups" do - visit groups_path - page.should have_content group.name + it "searches by URL" do + visit groups_path(anchor: "/?query=xyzzy") + expect(page).to have_content "No groups found" end end From f984871b23e262fa00a67ae6b7765c62073d4b9c Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Wed, 6 Jul 2016 11:14:13 +1000 Subject: [PATCH 13/23] Inject only needed enterprises into cart and checkout --- app/helpers/injection_helper.rb | 4 ++++ app/models/enterprise.rb | 4 ++-- app/views/checkout/edit.html.haml | 2 +- app/views/spree/orders/edit.html.haml | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/helpers/injection_helper.rb b/app/helpers/injection_helper.rb index 6432597632..032aee2cf7 100644 --- a/app/helpers/injection_helper.rb +++ b/app/helpers/injection_helper.rb @@ -5,6 +5,10 @@ module InjectionHelper inject_json_ams "enterprises", Enterprise.activated.includes(address: :state).all, Api::EnterpriseSerializer, enterprise_injection_data end + def inject_enterprise_and_relatives + inject_json_ams "enterprises", current_distributor.relatives_including_self.activated.includes(address: :state).all, Api::EnterpriseSerializer, enterprise_injection_data + end + def inject_shop_enterprises ocs = if current_order_cycle [current_order_cycle] diff --git a/app/models/enterprise.rb b/app/models/enterprise.rb index ef11c97e49..3802468ee9 100644 --- a/app/models/enterprise.rb +++ b/app/models/enterprise.rb @@ -231,8 +231,8 @@ class Enterprise < ActiveRecord::Base end def relatives_and_oc_producers(order_cycles) - enterprise_ids = Exchange.in_order_cycle(order_cycles).incoming.pluck :sender_id - Enterprise.relatives_of_one_union_others(id, enterprise_ids) + oc_producer_ids = Exchange.in_order_cycle(order_cycles).incoming.pluck :sender_id + Enterprise.relatives_of_one_union_others(id, oc_producer_ids) end def relatives_including_self diff --git a/app/views/checkout/edit.html.haml b/app/views/checkout/edit.html.haml index f0bef536db..b3d30ed442 100644 --- a/app/views/checkout/edit.html.haml +++ b/app/views/checkout/edit.html.haml @@ -1,7 +1,7 @@ - content_for(:title) do = t :checkout_title -= inject_enterprises += inject_enterprise_and_relatives .darkswarm.footer-pad - content_for :order_cycle_form do diff --git a/app/views/spree/orders/edit.html.haml b/app/views/spree/orders/edit.html.haml index 2fa5c043db..3417eb5e6a 100644 --- a/app/views/spree/orders/edit.html.haml +++ b/app/views/spree/orders/edit.html.haml @@ -1,7 +1,7 @@ - content_for(:title) do = t :orders_edit_title -= inject_enterprises += inject_enterprise_and_relatives .darkswarm - content_for :order_cycle_form do From d3c423f7ce7f75751c0e042227a6c00fb86a94ce Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 6 Jul 2016 11:56:41 +1000 Subject: [PATCH 14/23] Only perform URL search once, not every time map tiles change --- .../javascripts/darkswarm/directives/map_search.js.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/darkswarm/directives/map_search.js.coffee b/app/assets/javascripts/darkswarm/directives/map_search.js.coffee index a074539a23..af82766d62 100644 --- a/app/assets/javascripts/darkswarm/directives/map_search.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/map_search.js.coffee @@ -42,7 +42,7 @@ Darkswarm.directive 'mapSearch', ($timeout, Search) -> # When the map loads, and we have a search from ?query, perform that search scope.performUrlSearch = (map) -> - google.maps.event.addListener map, "tilesloaded", => + google.maps.event.addListenerOnce map, "idle", => google.maps.event.trigger(scope.input, 'focus'); google.maps.event.trigger(scope.input, 'keydown', {keyCode: 13}); From f733c7f20795090dd2d875ca32f2906d3aed722d Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Wed, 6 Jul 2016 12:45:12 +1000 Subject: [PATCH 15/23] Include shop enterprise on shop front --- app/helpers/injection_helper.rb | 2 +- app/models/enterprise.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/helpers/injection_helper.rb b/app/helpers/injection_helper.rb index 032aee2cf7..6db2e583bc 100644 --- a/app/helpers/injection_helper.rb +++ b/app/helpers/injection_helper.rb @@ -15,7 +15,7 @@ module InjectionHelper else OrderCycle.not_closed.with_distributor(current_distributor) end - inject_json_ams "enterprises", current_distributor.relatives_and_oc_producers(ocs).activated.includes(address: :state).all, Api::EnterpriseSerializer, enterprise_injection_data + inject_json_ams "enterprises", current_distributor.plus_relatives_and_oc_producers(ocs).activated.includes(address: :state).all, Api::EnterpriseSerializer, enterprise_injection_data end def inject_group_enterprises diff --git a/app/models/enterprise.rb b/app/models/enterprise.rb index 3802468ee9..80414d5116 100644 --- a/app/models/enterprise.rb +++ b/app/models/enterprise.rb @@ -230,9 +230,9 @@ class Enterprise < ActiveRecord::Base ", self.id, self.id) end - def relatives_and_oc_producers(order_cycles) + def plus_relatives_and_oc_producers(order_cycles) oc_producer_ids = Exchange.in_order_cycle(order_cycles).incoming.pluck :sender_id - Enterprise.relatives_of_one_union_others(id, oc_producer_ids) + Enterprise.relatives_of_one_union_others(id, oc_producer_ids | [id]) end def relatives_including_self From 13c8f0a230bc24ddbc5a43ea4d69604897ae0453 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 6 Jul 2016 15:29:04 +1000 Subject: [PATCH 16/23] Improve spec reliability It seems that the success message on the customers page is disappearing before the spec can detect it. This seems unlikely since it's present for 3 s, but this is my best theory right now. --- .../admin/index_utils/directives/obj_for_update.js.coffee | 2 +- spec/features/admin/customers_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/admin/index_utils/directives/obj_for_update.js.coffee b/app/assets/javascripts/admin/index_utils/directives/obj_for_update.js.coffee index 81cf58fd1e..18c800ce7f 100644 --- a/app/assets/javascripts/admin/index_utils/directives/obj_for_update.js.coffee +++ b/app/assets/javascripts/admin/index_utils/directives/obj_for_update.js.coffee @@ -24,7 +24,7 @@ angular.module("admin.indexUtils").directive "objForUpdate", (switchClass, pendi scope.savedValue = value scope.success = -> - switchClass( element, "update-success", ["update-pending", "update-error"], 3000 ) + switchClass( element, "update-success", ["update-pending", "update-error"], 5000 ) scope.pending = -> switchClass( element, "update-pending", ["update-error", "update-success"], false ) diff --git a/spec/features/admin/customers_spec.rb b/spec/features/admin/customers_spec.rb index 61caae507f..89893860df 100644 --- a/spec/features/admin/customers_spec.rb +++ b/spec/features/admin/customers_spec.rb @@ -60,7 +60,7 @@ feature 'Customers' do create(:order, customer: customer1) expect{ within "tr#c_#{customer1.id}" do - find("a.delete-customer").click + find("a.delete-customer").trigger('click') end expect(page).to have_selector "#info-dialog .text", text: "Delete failed: customer has associated orders" click_button "OK" @@ -115,7 +115,7 @@ feature 'Customers' do expect(customer1.tag_list).to eq [] end - it "prevents duplicate codes from being saved" do + it "prevents duplicate codes from being saved", retry: 3 do select2_select managed_distributor1.name, from: "shop_id" within "tr#c_#{customer1.id}" do From b5a9a1b6bf37021d0234c53084b454ed6732d54b Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 6 Jul 2016 16:14:25 +1000 Subject: [PATCH 17/23] Add translation for business_model_configuration --- config/locales/en.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/config/locales/en.yml b/config/locales/en.yml index e103001337..253b76a106 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -64,6 +64,7 @@ en: free: "free" plus_tax: "plus GST" total_monthly_bill_incl_tax: "Total Monthly Bill (Incl. Tax)" + business_model_configuration: "Business model configuration" say_no: "No" say_yes: "Yes" From e3732849347a2c30fe634a6acd4727b52b6bab00 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 6 Jul 2016 16:14:32 +1000 Subject: [PATCH 18/23] Fix intermittent spec failure --- spec/features/admin/business_model_configuration_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/features/admin/business_model_configuration_spec.rb b/spec/features/admin/business_model_configuration_spec.rb index 05d5367437..ab5e4fd2e7 100644 --- a/spec/features/admin/business_model_configuration_spec.rb +++ b/spec/features/admin/business_model_configuration_spec.rb @@ -42,6 +42,7 @@ feature 'Business Model Configuration' do click_button "Update" + expect(page).to have_content "Business model configuration has been successfully updated!" expect(Spree::Config.account_invoices_monthly_fixed).to eq 10 expect(Spree::Config.account_invoices_monthly_rate).to eq 0.05 expect(Spree::Config.account_invoices_monthly_cap).to eq 30 From 8e73a2e0d6dc7bbc069927e848ea9bbf889be623 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Wed, 6 Jul 2016 16:20:07 +1000 Subject: [PATCH 19/23] Dereference enterprises and taxons later --- .../darkswarm/services/dereferencer.js.coffee | 4 +++- .../darkswarm/services/enterprises.js.coffee | 23 +++++++++---------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/app/assets/javascripts/darkswarm/services/dereferencer.js.coffee b/app/assets/javascripts/darkswarm/services/dereferencer.js.coffee index b4817e0e2d..5265cf7e99 100644 --- a/app/assets/javascripts/darkswarm/services/dereferencer.js.coffee +++ b/app/assets/javascripts/darkswarm/services/dereferencer.js.coffee @@ -7,10 +7,12 @@ Darkswarm.factory 'Dereferencer', -> unreferenced = [] if source && target for object, i in source + # skip empty entries in sparse array + continue unless source.hasOwnProperty(i) key = object?.id if data.hasOwnProperty(key) target[i] = data[key] else delete target[i] - unreferenced[i] = source[i] + unreferenced[i] = object unreferenced diff --git a/app/assets/javascripts/darkswarm/services/enterprises.js.coffee b/app/assets/javascripts/darkswarm/services/enterprises.js.coffee index 6473b58442..73dbd1627b 100644 --- a/app/assets/javascripts/darkswarm/services/enterprises.js.coffee +++ b/app/assets/javascripts/darkswarm/services/enterprises.js.coffee @@ -9,7 +9,6 @@ Darkswarm.factory 'Enterprises', (enterprises, CurrentHub, Taxons, Dereferencer, @enterprises_by_id[enterprise.id] = enterprise # Replace enterprise and taxons ids with actual objects. @dereferenceEnterprises() - @dereferenceTaxons() @visible_enterprises = visibleFilter @enterprises @producers = @visible_enterprises.filter (enterprise)-> enterprise.category in ["producer_hub", "producer_shop", "producer"] @@ -23,19 +22,19 @@ Darkswarm.factory 'Enterprises', (enterprises, CurrentHub, Taxons, Dereferencer, @dereferenceEnterprise enterprise dereferenceEnterprise: (enterprise) -> + @dereferenceProperty(enterprise, 'hubs', @enterprises_by_id) + @dereferenceProperty(enterprise, 'producers', @enterprises_by_id) + @dereferenceProperty(enterprise, 'taxons', Taxons.taxons_by_id) + @dereferenceProperty(enterprise, 'supplied_taxons', Taxons.taxons_by_id) + + dereferenceProperty: (enterprise, property, data) -> # keep unreferenced enterprise ids # in case we dereference again after adding more enterprises - hubs = enterprise.unreferenced_hubs || enterprise.hubs - enterprise.unreferenced_hubs = - Dereferencer.dereference_from hubs, enterprise.hubs, @enterprises_by_id - producers = enterprise.unreferenced_producers || enterprise.producers - enterprise.unreferenced_producers = - Dereferencer.dereference_from producers, enterprise.producers, @enterprises_by_id - - dereferenceTaxons: -> - for enterprise in @enterprises - Dereferencer.dereference enterprise.taxons, Taxons.taxons_by_id - Dereferencer.dereference enterprise.supplied_taxons, Taxons.taxons_by_id + enterprise.unreferenced |= {} + collection = enterprise[property] + unreferenced = enterprise.unreferenced[property] || collection + enterprise.unreferenced[property] = + Dereferencer.dereference_from unreferenced, collection, data addEnterprises: (new_enterprises) -> return unless new_enterprises && new_enterprises.length From 0ff1c95c3df495d8e35bd250e17f830bb1f56d97 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Wed, 13 Jul 2016 12:08:11 +1000 Subject: [PATCH 20/23] Keep unreferenced entries when dereferencing in js --- app/assets/javascripts/darkswarm/services/dereferencer.js.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/app/assets/javascripts/darkswarm/services/dereferencer.js.coffee b/app/assets/javascripts/darkswarm/services/dereferencer.js.coffee index 5265cf7e99..b68a716a4d 100644 --- a/app/assets/javascripts/darkswarm/services/dereferencer.js.coffee +++ b/app/assets/javascripts/darkswarm/services/dereferencer.js.coffee @@ -13,6 +13,5 @@ Darkswarm.factory 'Dereferencer', -> if data.hasOwnProperty(key) target[i] = data[key] else - delete target[i] unreferenced[i] = object unreferenced From e693f71775e8a3e19698f0645757db5678d37b1b Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Wed, 13 Jul 2016 13:54:32 +1000 Subject: [PATCH 21/23] Inject only needed enterprises into order confirmation page --- app/views/spree/orders/show.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/spree/orders/show.html.haml b/app/views/spree/orders/show.html.haml index 438a611a68..a802d451ea 100644 --- a/app/views/spree/orders/show.html.haml +++ b/app/views/spree/orders/show.html.haml @@ -1,7 +1,7 @@ - content_for(:title) do = t :orders_show_title -= inject_enterprises += inject_enterprise_and_relatives if current_distributor.present? .darkswarm - content_for :order_cycle_form do From af6d0ec107be635a2018c3ee63c885fcc39402d8 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Wed, 13 Jul 2016 13:54:55 +1000 Subject: [PATCH 22/23] Remove unused code from order confirmation page --- app/views/spree/orders/show.html.haml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/views/spree/orders/show.html.haml b/app/views/spree/orders/show.html.haml index a802d451ea..e4cb3b1980 100644 --- a/app/views/spree/orders/show.html.haml +++ b/app/views/spree/orders/show.html.haml @@ -4,14 +4,6 @@ = inject_enterprise_and_relatives if current_distributor.present? .darkswarm - - content_for :order_cycle_form do - %strong.avenir - = t :orders_show_time - - if @order.order_cycle - = @order.order_cycle.pickup_time_for(@order.distributor) - - else - = @order.distributor.next_collection_at - = render "shopping_shared/details" if current_distributor.present? %fieldset#order_summary.footer-pad{"data-hook" => ""} From ddb54d1924369fba41568fce3489cd993168d211 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Fri, 15 Jul 2016 17:43:26 +1000 Subject: [PATCH 23/23] Delete fee on payment method if payment invalid PayPalExpress is always creating two payments. The first one is invalidated and the second one succeeds. Without deleting the old fee on the invalidated payment, the order lists the fee twice. --- app/helpers/checkout_helper.rb | 1 + app/models/spree/payment_decorator.rb | 7 ++++++- app/views/checkout/_summary.html.haml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/helpers/checkout_helper.rb b/app/helpers/checkout_helper.rb index 66d98d7862..6359cb01bd 100644 --- a/app/helpers/checkout_helper.rb +++ b/app/helpers/checkout_helper.rb @@ -6,6 +6,7 @@ module CheckoutHelper # Remove empty tax adjustments and (optionally) shipping fees adjustments.reject! { |a| a.originator_type == 'Spree::TaxRate' && a.amount == 0 } adjustments.reject! { |a| a.originator_type == 'Spree::ShippingMethod' } if exclude.include? :shipping + adjustments.reject! { |a| a.originator_type == 'Spree::PaymentMethod' } if exclude.include? :payment adjustments.reject! { |a| a.source_type == 'Spree::LineItem' } if exclude.include? :line_item enterprise_fee_adjustments = adjustments.select { |a| a.originator_type == 'EnterpriseFee' && a.source_type != 'Spree::LineItem' } diff --git a/app/models/spree/payment_decorator.rb b/app/models/spree/payment_decorator.rb index d178e1de54..dbee3cfd0f 100644 --- a/app/models/spree/payment_decorator.rb +++ b/app/models/spree/payment_decorator.rb @@ -5,7 +5,12 @@ module Spree after_save :ensure_correct_adjustment, :update_order def ensure_correct_adjustment - if adjustment + # Don't charge for invalid payments. + # PayPalExpress always creates a payment that is invalidated later. + # Unknown: What about failed payments? + if state == "invalid" + adjustment.andand.destroy + elsif adjustment adjustment.originator = payment_method adjustment.label = adjustment_label adjustment.save diff --git a/app/views/checkout/_summary.html.haml b/app/views/checkout/_summary.html.haml index a3b61c5ded..0fec419556 100644 --- a/app/views/checkout/_summary.html.haml +++ b/app/views/checkout/_summary.html.haml @@ -9,7 +9,7 @@ = t :checkout_cart_total %td.cart-total.text-right= display_checkout_subtotal(@order) - - checkout_adjustments_for(current_order, exclude: [:shipping, :line_item]).reject{ |a| a.amount == 0 }.each do |adjustment| + - checkout_adjustments_for(current_order, exclude: [:shipping, :payment, :line_item]).reject{ |a| a.amount == 0 }.each do |adjustment| %tr %th= adjustment.label %td.text-right= adjustment.display_amount.to_html