mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
Merge pull request #3801 from Matt-Yorkley/need_for_speed
Fix /maps performance
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
Darkswarm.factory "EnterpriseModal", ($modal, $rootScope)->
|
||||
Darkswarm.factory "EnterpriseModal", ($modal, $rootScope, $http)->
|
||||
# Build a modal popup for an enterprise.
|
||||
new class EnterpriseModal
|
||||
open: (enterprise)->
|
||||
scope = $rootScope.$new(true) # Spawn an isolate to contain the enterprise
|
||||
scope.embedded_layout = window.location.search.indexOf("embedded_shopfront=true") != -1
|
||||
|
||||
scope.enterprise = enterprise
|
||||
$modal.open(templateUrl: "enterprise_modal.html", scope: scope)
|
||||
$http.get("/api/enterprises/" + enterprise.id + "/shopfront").success (data) ->
|
||||
scope.enterprise = data
|
||||
$modal.open(templateUrl: "enterprise_modal.html", scope: scope)
|
||||
.error (data) ->
|
||||
console.error(data)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
module Api
|
||||
class EnterprisesController < Spree::Api::BaseController
|
||||
class EnterprisesController < BaseController
|
||||
|
||||
before_filter :override_owner, only: [:create, :update]
|
||||
before_filter :check_type, only: :update
|
||||
@@ -47,6 +47,12 @@ module Api
|
||||
end
|
||||
end
|
||||
|
||||
def shopfront
|
||||
enterprise = Enterprise.find_by_id(params[:id])
|
||||
|
||||
render text: Api::EnterpriseShopfrontSerializer.new(enterprise).to_json, status: :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def override_owner
|
||||
|
||||
@@ -10,6 +10,14 @@ module InjectionHelper
|
||||
)
|
||||
end
|
||||
|
||||
def inject_enterprise_shopfront_list
|
||||
inject_json_ams(
|
||||
'enterprises',
|
||||
Enterprise.activated.includes(address: :state).all,
|
||||
Api::EnterpriseShopfrontListSerializer
|
||||
)
|
||||
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
|
||||
|
||||
52
app/serializers/api/enterprise_shopfront_list_serializer.rb
Normal file
52
app/serializers/api/enterprise_shopfront_list_serializer.rb
Normal file
@@ -0,0 +1,52 @@
|
||||
# Represents the minimum details of an Enterprise when all shopfronts are being listed
|
||||
module Api
|
||||
class EnterpriseShopfrontListSerializer < ActiveModel::Serializer
|
||||
attributes :name, :id, :latitude, :longitude, :is_primary_producer, :is_distributor,
|
||||
:visible, :path, :icon, :icon_font, :producer_icon_font
|
||||
|
||||
has_one :address, serializer: Api::AddressSerializer
|
||||
|
||||
def path
|
||||
enterprise_shop_path(enterprise)
|
||||
end
|
||||
|
||||
def icon
|
||||
icons = {
|
||||
hub: "/assets/map_005-hub.svg",
|
||||
hub_profile: "/assets/map_006-hub-profile.svg",
|
||||
producer_hub: "/assets/map_005-hub.svg",
|
||||
producer_shop: "/assets/map_003-producer-shop.svg",
|
||||
producer: "/assets/map_001-producer-only.svg",
|
||||
}
|
||||
icons[enterprise.category]
|
||||
end
|
||||
|
||||
def icon_font
|
||||
icon_fonts = {
|
||||
hub: "ofn-i_063-hub",
|
||||
hub_profile: "ofn-i_064-hub-reversed",
|
||||
producer_hub: "ofn-i_063-hub",
|
||||
producer_shop: "ofn-i_059-producer",
|
||||
producer: "ofn-i_059-producer",
|
||||
}
|
||||
icon_fonts[enterprise.category]
|
||||
end
|
||||
|
||||
def producer_icon_font
|
||||
icon_fonts = {
|
||||
hub: "",
|
||||
hub_profile: "",
|
||||
producer_hub: "ofn-i_059-producer",
|
||||
producer_shop: "ofn-i_059-producer",
|
||||
producer: "ofn-i_059-producer",
|
||||
}
|
||||
icon_fonts[enterprise.category]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def enterprise
|
||||
object
|
||||
end
|
||||
end
|
||||
end
|
||||
133
app/serializers/api/enterprise_shopfront_serializer.rb
Normal file
133
app/serializers/api/enterprise_shopfront_serializer.rb
Normal file
@@ -0,0 +1,133 @@
|
||||
# Represents the properties of an Enterprise when viewing the details of listed shopfronts
|
||||
module Api
|
||||
class EnterpriseShopfrontSerializer < ActiveModel::Serializer
|
||||
include SerializerHelper
|
||||
|
||||
attributes :name, :id, :description, :latitude, :longitude, :long_description, :website,
|
||||
:instagram, :linkedin, :twitter, :facebook, :is_primary_producer, :is_distributor,
|
||||
:phone, :visible, :email_address, :hash, :logo, :promo_image, :path, :category,
|
||||
:active, :producers, :orders_close_at, :hubs, :taxons, :supplied_taxons, :pickup,
|
||||
:delivery
|
||||
|
||||
has_one :address, serializer: Api::AddressSerializer
|
||||
has_many :supplied_properties, serializer: Api::PropertySerializer
|
||||
has_many :distributed_properties, serializer: Api::PropertySerializer
|
||||
|
||||
def orders_close_at
|
||||
OrderCycle.with_distributor(enterprise).soonest_closing.first.andand.orders_close_at
|
||||
end
|
||||
|
||||
def active
|
||||
enterprise.ready_for_checkout? && OrderCycle.active.with_distributor(enterprise).exists?
|
||||
end
|
||||
|
||||
def pickup
|
||||
shipping_types? :pickup
|
||||
end
|
||||
|
||||
def delivery
|
||||
shipping_types? :delivery
|
||||
end
|
||||
|
||||
def email_address
|
||||
enterprise.email_address.to_s.reverse
|
||||
end
|
||||
|
||||
def hash
|
||||
enterprise.to_param
|
||||
end
|
||||
|
||||
def logo
|
||||
enterprise.logo(:medium) if enterprise.logo?
|
||||
end
|
||||
|
||||
def promo_image
|
||||
enterprise.promo_image(:large) if enterprise.promo_image?
|
||||
end
|
||||
|
||||
def path
|
||||
enterprise_shop_path(enterprise)
|
||||
end
|
||||
|
||||
def producers
|
||||
ActiveModel::ArraySerializer.new(
|
||||
enterprise.suppliers, each_serializer: Api::EnterpriseThinSerializer
|
||||
)
|
||||
end
|
||||
|
||||
def hubs
|
||||
ActiveModel::ArraySerializer.new(
|
||||
enterprise.distributors, each_serializer: Api::EnterpriseThinSerializer
|
||||
)
|
||||
end
|
||||
|
||||
def taxons
|
||||
ActiveModel::ArraySerializer.new(
|
||||
enterprise.distributed_taxons, each_serializer: Api::TaxonSerializer
|
||||
)
|
||||
end
|
||||
|
||||
def supplied_taxons
|
||||
ActiveModel::ArraySerializer.new(
|
||||
enterprise.supplied_taxons, each_serializer: Api::TaxonSerializer
|
||||
)
|
||||
end
|
||||
|
||||
def supplied_properties
|
||||
(product_properties + producer_properties).uniq do |property_object|
|
||||
property_object.property.presentation
|
||||
end
|
||||
end
|
||||
|
||||
def distributed_properties
|
||||
(distributed_product_properties + distributed_producer_properties).uniq do |property_object|
|
||||
property_object.property.presentation
|
||||
end
|
||||
end
|
||||
|
||||
def distributed_product_properties
|
||||
properties = Spree::Property.joins(products: { variants: { exchanges: :order_cycle } })
|
||||
.merge(Exchange.outgoing)
|
||||
.merge(Exchange.to_enterprise(enterprise))
|
||||
.select('DISTINCT spree_properties.*')
|
||||
|
||||
return properties.merge(OrderCycle.active) if active
|
||||
properties
|
||||
end
|
||||
|
||||
def distributed_producer_properties
|
||||
properties = Spree::Property.joins(
|
||||
producer_properties: {
|
||||
producer: { supplied_products: { variants: { exchanges: :order_cycle } } }
|
||||
}
|
||||
)
|
||||
.merge(Exchange.outgoing).merge(Exchange.to_enterprise(enterprise))
|
||||
.select('DISTINCT spree_properties.*')
|
||||
|
||||
return properties.merge(OrderCycle.active) if active
|
||||
properties
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def product_properties
|
||||
enterprise.supplied_products.flat_map(&:properties)
|
||||
end
|
||||
|
||||
def producer_properties
|
||||
enterprise.properties
|
||||
end
|
||||
|
||||
def enterprise
|
||||
object
|
||||
end
|
||||
|
||||
def shipping_types?(type)
|
||||
require_shipping = type == :delivery ? 't' : 'f'
|
||||
Spree::ShippingMethod.
|
||||
joins(:distributor_shipping_methods).
|
||||
where('distributors_shipping_methods.distributor_id = ?', enterprise.id).
|
||||
where("spree_shipping_methods.require_ship_address = '#{require_shipping}'").exists?
|
||||
end
|
||||
end
|
||||
end
|
||||
21
app/serializers/api/enterprise_thin_serializer.rb
Normal file
21
app/serializers/api/enterprise_thin_serializer.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
module Api
|
||||
class EnterpriseThinSerializer < ActiveModel::Serializer
|
||||
attributes :name, :id, :active, :path
|
||||
|
||||
has_one :address, serializer: Api::AddressSerializer
|
||||
|
||||
def active
|
||||
enterprise.ready_for_checkout? && OrderCycle.active.with_distributor(enterprise).exists?
|
||||
end
|
||||
|
||||
def path
|
||||
enterprise_shop_path(enterprise)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def enterprise
|
||||
object
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,7 +1,7 @@
|
||||
- content_for(:title) do
|
||||
= t :label_map
|
||||
|
||||
= inject_enterprises
|
||||
= inject_enterprise_shopfront_list
|
||||
|
||||
.map-container{"fill-vertical" => true}
|
||||
%map{"ng-controller" => "MapCtrl"}
|
||||
|
||||
@@ -96,6 +96,10 @@ Openfoodnetwork::Application.routes.draw do
|
||||
|
||||
resource :logo, only: [:destroy]
|
||||
resource :promo_image, only: [:destroy]
|
||||
|
||||
member do
|
||||
get :shopfront
|
||||
end
|
||||
end
|
||||
|
||||
resources :order_cycles do
|
||||
|
||||
@@ -81,5 +81,27 @@ module Api
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "fetching shopfronts data" do
|
||||
let!(:hub) {
|
||||
create(:distributor_enterprise, with_payment_and_shipping: true, name: 'Shopfront Test Hub')
|
||||
}
|
||||
let!(:producer) { create(:supplier_enterprise, name: 'Shopfront Test Producer') }
|
||||
let!(:category) { create(:taxon, name: 'Fruit') }
|
||||
let!(:product) { create(:product, supplier: producer, primary_taxon: category ) }
|
||||
let!(:relationship) { create(:enterprise_relationship, parent: hub, child: producer) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:spree_current_user) { Spree::User.anonymous! }
|
||||
end
|
||||
|
||||
it "returns data for an enterprise" do
|
||||
spree_get :shopfront, id: producer.id, format: :json
|
||||
|
||||
expect(json_response['name']).to eq 'Shopfront Test Producer'
|
||||
expect(json_response['hubs'][0]['name']).to eq 'Shopfront Test Hub'
|
||||
expect(json_response['supplied_taxons'][0]['name']).to eq 'Fruit'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Api::EnterpriseShopfrontListSerializer do
|
||||
let(:enterprise) { create(:distributor_enterprise) }
|
||||
let(:serializer) {
|
||||
Api::EnterpriseShopfrontListSerializer.new enterprise
|
||||
}
|
||||
|
||||
it "serializes enterprise attributes" do
|
||||
expect(serializer.to_json).to match enterprise.name
|
||||
end
|
||||
|
||||
it "serializes shopfront path" do
|
||||
expect(serializer.to_json).to match enterprise_shop_path(enterprise)
|
||||
end
|
||||
|
||||
it "serializes icons" do
|
||||
expect(serializer.to_json).to match "map_005-hub.svg"
|
||||
end
|
||||
end
|
||||
50
spec/serializers/api/enterprise_shopfront_serializer_spec.rb
Normal file
50
spec/serializers/api/enterprise_shopfront_serializer_spec.rb
Normal file
@@ -0,0 +1,50 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Api::EnterpriseShopfrontSerializer do
|
||||
let!(:hub) { create(:distributor_enterprise, with_payment_and_shipping: true) }
|
||||
let!(:producer) { create(:supplier_enterprise) }
|
||||
let!(:relationship) { create(:enterprise_relationship, parent: hub, child: producer) }
|
||||
|
||||
let!(:taxon1) { create(:taxon, name: 'Meat') }
|
||||
let!(:taxon2) { create(:taxon, name: 'Veg') }
|
||||
let!(:product) { create(:product, supplier: producer, primary_taxon: taxon1, taxons: [taxon1, taxon2] ) }
|
||||
|
||||
let(:close_time) { 2.days.from_now }
|
||||
let!(:oc) { create(:simple_order_cycle, orders_close_at: close_time, distributors: [hub]) }
|
||||
|
||||
let!(:ex) {
|
||||
create(:exchange, order_cycle: oc, incoming: false,
|
||||
sender: producer, receiver: hub)
|
||||
}
|
||||
|
||||
let(:serializer) { Api::EnterpriseShopfrontSerializer.new hub }
|
||||
|
||||
before do
|
||||
ex.variants << product.variants.first
|
||||
end
|
||||
|
||||
it "serializes next order cycle close time" do
|
||||
expect(serializer.serializable_hash[:orders_close_at]).to match oc.orders_close_at
|
||||
end
|
||||
|
||||
it "serializes shipping method types" do
|
||||
expect(serializer.serializable_hash[:pickup]).to eq false
|
||||
expect(serializer.serializable_hash[:delivery]).to eq true
|
||||
end
|
||||
|
||||
it "serialises an array of hubs" do
|
||||
expect(serializer.serializable_hash[:hubs]).to be_a ActiveModel::ArraySerializer
|
||||
expect(serializer.serializable_hash[:hubs].to_json).to match hub.name
|
||||
end
|
||||
|
||||
it "serialises an array of producers" do
|
||||
expect(serializer.serializable_hash[:producers]).to be_a ActiveModel::ArraySerializer
|
||||
expect(serializer.serializable_hash[:producers].to_json).to match producer.name
|
||||
end
|
||||
|
||||
it "serialises taxons" do
|
||||
expect(serializer.serializable_hash[:taxons]).to be_a ActiveModel::ArraySerializer
|
||||
expect(serializer.serializable_hash[:taxons].to_json).to match 'Meat'
|
||||
expect(serializer.serializable_hash[:taxons].to_json).to match 'Veg'
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user