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 fa6378afe29..099f2a39e41 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 2061f95ea15..dbe092b0be9 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 00000000000..e66ec7c176b --- /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 2dddfbc7ef2..b030c6e723a 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 7f627ec73aa..83d7c42f622 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 @@ def check_permalink end end - private def clean_permalink diff --git a/app/helpers/injection_helper.rb b/app/helpers/injection_helper.rb index 50b9c93fcab..d76f37bf621 100644 --- a/app/helpers/injection_helper.rb +++ b/app/helpers/injection_helper.rb @@ -5,6 +5,10 @@ def inject_enterprises 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 d635f681640..569009db092 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 f1b96de181f..cd7c7780c46 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -55,6 +55,7 @@ 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 c01a9416591..f65c8854dcc 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 dbe092b0be9..40f195c6f50 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 b030c6e723a..6473b58442b 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 d76f37bf621..6432597632e 100644 --- a/app/helpers/injection_helper.rb +++ b/app/helpers/injection_helper.rb @@ -6,7 +6,12 @@ def inject_enterprises 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 554529d7f26..eca5a44da22 100644 --- a/app/models/enterprise.rb +++ b/app/models/enterprise.rb @@ -220,6 +220,22 @@ def relatives ", 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 7dc9f474da7..b449b4d0833 100644 --- a/spec/features/consumer/shopping/shopping_spec.rb +++ b/spec/features/consumer/shopping/shopping_spec.rb @@ -34,7 +34,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 279ead2630c..d7654617e1f 100644 --- a/spec/support/request/shop_workflow.rb +++ b/spec/support/request/shop_workflow.rb @@ -29,6 +29,15 @@ def toggle_accordion(name) 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 40f195c6f50..b4817e0e2d4 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 83d7c42f622..70d240abd1d 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 eca5a44da22..ef11c97e493 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 @@ def relatives 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 d7654617e1f..01c24bee055 100644 --- a/spec/support/request/shop_workflow.rb +++ b/spec/support/request/shop_workflow.rb @@ -29,19 +29,24 @@ def toggle_accordion(name) 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 089838a1b1d..b4778a12aa4 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 @@ def columns 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 55c8bd11974..f37dcefa025 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 e67ce529a5c..3e546b82b3a 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 3e546b82b3a..cb9dce98b46 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 00000000000..9df5fd0d4b2 --- /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 cb9dce98b46..6f8aef6dc8a 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 af497a4195d..a21bdb74605 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 e4a22e540c6..75bb99f9d75 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 9df5fd0d4b2..0dcda8f59a8 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 6f8aef6dc8a..7a3e633384f 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 7a3e633384f..a074539a23b 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 | 61 ++++++++++------- spec/features/consumer/shops_spec.rb | 86 ++++++++++++++---------- 2 files changed, 85 insertions(+), 62 deletions(-) diff --git a/spec/features/consumer/producers_spec.rb b/spec/features/consumer/producers_spec.rb index 634350af180..5c89a235297 100644 --- a/spec/features/consumer/producers_spec.rb +++ b/spec/features/consumer/producers_spec.rb @@ -27,45 +27,54 @@ producer1.set_producer_property 'Local', 'Victoria' producer2.set_producer_property 'Fair Trade', 'FT123' + end + - visit producers_path + it "searches by URL" do + visit producers_path(anchor: "/?query=xyzzy") + expect(page).to have_content "Sorry, no results found for xyzzy" end + context "on the producers page" do + before do + visit producers_path + end - it "filters by taxon" do - toggle_filters + it "filters by taxon" do + toggle_filters - toggle_filter 'Vegetables' + toggle_filter 'Vegetables' - page.should_not have_content producer1.name - page.should have_content producer2.name + page.should_not have_content producer1.name + page.should have_content producer2.name - toggle_filter 'Vegetables' - toggle_filter 'Fruit' + toggle_filter 'Vegetables' + toggle_filter 'Fruit' - page.should have_content producer1.name - page.should_not have_content producer2.name - end + 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 + 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' + # -- Taxons + page.should have_content 'Fruit' - # -- Properties - page.should have_content 'Organic' # Product property - page.should have_content 'Local' # Producer property - end + # -- 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 "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 + 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 8b1a709462b..0c5d3d7e09b 100644 --- a/spec/features/consumer/shops_spec.rb +++ b/spec/features/consumer/shops_spec.rb @@ -14,56 +14,70 @@ 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 "shows hubs" do + page.should have_content distributor.name + expand_active_table_node distributor.name + page.should have_content "OUR PRODUCERS" + 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 + it "does not show invisible hubs" do + page.should_not have_content invisible_distributor.name + 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 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 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 + 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 - within ".reveal-modal" do - expect(page).to have_content 'Fruit' # Taxon - expect(page).to have_content 'Organic' # Producer property + 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 8fd47c49f83..91cbe0bf54c 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 e51ac39ea27..5ea96ac17e3 100644 --- a/spec/features/consumer/groups_spec.rb +++ b/spec/features/consumer/groups_spec.rb @@ -12,8 +12,8 @@ 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 6432597632e..032aee2cf7b 100644 --- a/app/helpers/injection_helper.rb +++ b/app/helpers/injection_helper.rb @@ -5,6 +5,10 @@ def inject_enterprises 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 ef11c97e493..3802468ee98 100644 --- a/app/models/enterprise.rb +++ b/app/models/enterprise.rb @@ -231,8 +231,8 @@ def relatives 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 f0bef536dbe..b3d30ed442d 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 2fa5c043db6..3417eb5e6a2 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 a074539a23b..af82766d624 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 032aee2cf7b..6db2e583bcc 100644 --- a/app/helpers/injection_helper.rb +++ b/app/helpers/injection_helper.rb @@ -15,7 +15,7 @@ def inject_shop_enterprises 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 3802468ee98..80414d51161 100644 --- a/app/models/enterprise.rb +++ b/app/models/enterprise.rb @@ -230,9 +230,9 @@ def relatives ", 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 81cf58fd1ea..18c800ce7fc 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 61caae507f2..89893860df3 100644 --- a/spec/features/admin/customers_spec.rb +++ b/spec/features/admin/customers_spec.rb @@ -60,7 +60,7 @@ 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 @@ 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 e103001337c..253b76a106d 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 05d5367437e..ab5e4fd2e76 100644 --- a/spec/features/admin/business_model_configuration_spec.rb +++ b/spec/features/admin/business_model_configuration_spec.rb @@ -42,6 +42,7 @@ 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 b4817e0e2d4..5265cf7e998 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 6473b58442b..73dbd1627bb 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 5265cf7e998..b68a716a4d6 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 438a611a683..a802d451ead 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 a802d451ead..e4cb3b19804 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 66d98d78625..6359cb01bd8 100644 --- a/app/helpers/checkout_helper.rb +++ b/app/helpers/checkout_helper.rb @@ -6,6 +6,7 @@ def checkout_adjustments_for(order, opts={}) # 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 d178e1de548..dbee3cfd0fe 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 a3b61c5ded7..0fec4195562 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