mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
Merge pull request #3836 from Matt-Yorkley/fast_and_furious2
Improve /shops, /producers, and /groups performance
This commit is contained in:
@@ -1,12 +0,0 @@
|
||||
Darkswarm.controller "GroupEnterpriseNodeCtrl", ($scope, CurrentHub) ->
|
||||
|
||||
$scope.active = false
|
||||
|
||||
$scope.toggle = ->
|
||||
$scope.active = !$scope.active
|
||||
|
||||
$scope.open = ->
|
||||
$scope.active
|
||||
|
||||
$scope.current = ->
|
||||
$scope.hub.id is CurrentHub.hub.id
|
||||
@@ -1,22 +1,6 @@
|
||||
Darkswarm.controller "GroupPageCtrl", ($scope, group_enterprises, Enterprises, MapConfiguration, OfnMap, visibleFilter, Navigation) ->
|
||||
Darkswarm.controller "GroupPageCtrl", ($scope, enterprises, Enterprises, MapConfiguration, OfnMap) ->
|
||||
$scope.Enterprises = Enterprises
|
||||
|
||||
all_enterprises_by_id = Enterprises.enterprises_by_id
|
||||
|
||||
dereferenced_enterprises = group_enterprises.map (enterprise) =>
|
||||
all_enterprises_by_id[enterprise.id]
|
||||
|
||||
visible_enterprises = visibleFilter dereferenced_enterprises
|
||||
|
||||
# TODO: this is duplicate code with app/assets/javascripts/darkswarm/services/enterprises.js.coffee
|
||||
# It would be better to load only the needed enterprises (group + related shops).
|
||||
$scope.group_producers = visible_enterprises.filter (enterprise) ->
|
||||
enterprise.category in ["producer_hub", "producer_shop", "producer"]
|
||||
$scope.group_hubs = visible_enterprises.filter (enterprise) ->
|
||||
enterprise.category in ["hub", "hub_profile", "producer_hub", "producer_shop"]
|
||||
|
||||
$scope.producers_to_filter = $scope.group_producers
|
||||
|
||||
$scope.map = angular.copy MapConfiguration.options
|
||||
$scope.mapMarkers = OfnMap.enterprise_markers visible_enterprises
|
||||
$scope.embedded_layout = window.location.search.indexOf("embedded_shopfront=true") != -1
|
||||
$scope.mapMarkers = OfnMap.enterprise_markers enterprises
|
||||
$scope.embedded_layout = window.location.search.indexOf("embedded_shopfront=true") != -1
|
||||
|
||||
@@ -1,9 +1,44 @@
|
||||
Darkswarm.controller "HubNodeCtrl", ($scope, HashNavigation, Navigation, $location, $templateCache, CurrentHub) ->
|
||||
$scope.toggle = (e) ->
|
||||
HashNavigation.toggle $scope.hub.hash if !angular.element(e.target).inheritedData('is-link')
|
||||
Darkswarm.controller "HubNodeCtrl", ($scope, HashNavigation, CurrentHub, $http, $timeout) ->
|
||||
$scope.shopfront_loading = false
|
||||
$scope.enterprise_details = []
|
||||
|
||||
$timeout ->
|
||||
if $scope.open()
|
||||
$scope.load_shopfront()
|
||||
|
||||
# Toggles shopfront tabs open/closed. Fetches enterprise details from the api, diplays them and adds them
|
||||
# to $scope.enterprise_details, or simply displays the details again if previously fetched
|
||||
$scope.toggle = (event) ->
|
||||
if $scope.open()
|
||||
$scope.toggle_tab(event)
|
||||
return
|
||||
|
||||
if $scope.enterprise_details[$scope.hub.id]
|
||||
$scope.hub = $scope.enterprise_details[$scope.hub.id]
|
||||
$scope.toggle_tab(event)
|
||||
return
|
||||
|
||||
$scope.load_shopfront(event)
|
||||
|
||||
$scope.load_shopfront = (event=null) ->
|
||||
$scope.shopfront_loading = true
|
||||
$scope.toggle_tab(event)
|
||||
|
||||
$http.get("/api/enterprises/" + $scope.hub.id + "/shopfront")
|
||||
.success (data) ->
|
||||
$scope.shopfront_loading = false
|
||||
$scope.hub = data
|
||||
$scope.enterprise_details[$scope.hub.id] = $scope.hub
|
||||
.error (data) ->
|
||||
console.error(data)
|
||||
|
||||
$scope.toggle_tab = (event) ->
|
||||
HashNavigation.toggle $scope.hub.hash if event && !angular.element(event.target).inheritedData('is-link')
|
||||
|
||||
# Returns boolean: pulldown tab is currently open/closed
|
||||
$scope.open = ->
|
||||
HashNavigation.active $scope.hub.hash
|
||||
|
||||
|
||||
# Returns boolean: is this hub the hub that the user is currently "shopping" in?
|
||||
$scope.current = ->
|
||||
$scope.hub.id is CurrentHub.hub.id
|
||||
|
||||
@@ -1,6 +1,39 @@
|
||||
Darkswarm.controller "ProducerNodeCtrl", ($scope, HashNavigation, $anchorScroll) ->
|
||||
$scope.toggle = ->
|
||||
HashNavigation.toggle $scope.producer.hash
|
||||
Darkswarm.controller "ProducerNodeCtrl", ($scope, HashNavigation, $anchorScroll, $http, $timeout) ->
|
||||
$scope.shopfront_loading = false
|
||||
$scope.enterprise_details = []
|
||||
|
||||
$timeout ->
|
||||
if $scope.open()
|
||||
$scope.load_shopfront()
|
||||
|
||||
# Toggles shopfront tabs open/closed. Fetches enterprise details from the api, diplays them and adds them
|
||||
# to $scope.enterprise_details, or simply displays the details again if previously fetched
|
||||
$scope.toggle = (event) ->
|
||||
if $scope.open()
|
||||
$scope.toggle_tab(event)
|
||||
return
|
||||
|
||||
if $scope.enterprise_details[$scope.producer.id]
|
||||
$scope.producer = $scope.enterprise_details[$scope.producer.id]
|
||||
$scope.toggle_tab(event)
|
||||
return
|
||||
|
||||
$scope.load_shopfront(event)
|
||||
|
||||
$scope.load_shopfront = (event=null) ->
|
||||
$scope.shopfront_loading = true
|
||||
$scope.toggle_tab(event)
|
||||
|
||||
$http.get("/api/enterprises/" + $scope.producer.id + "/shopfront")
|
||||
.success (data) ->
|
||||
$scope.shopfront_loading = false
|
||||
$scope.producer = data
|
||||
$scope.enterprise_details[$scope.producer.id] = $scope.producer
|
||||
.error (data) ->
|
||||
console.error(data)
|
||||
|
||||
$scope.toggle_tab = (event) ->
|
||||
HashNavigation.toggle $scope.producer.hash if event && !angular.element(event.target).inheritedData('is-link')
|
||||
|
||||
$scope.open = ->
|
||||
HashNavigation.active($scope.producer.hash)
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
Darkswarm.controller "AboutUsCtrl", ($scope, CurrentHub) ->
|
||||
$scope.CurrentHub = CurrentHub
|
||||
Darkswarm.controller "AboutUsCtrl", ($scope, Shopfront) ->
|
||||
$scope.shopfront = Shopfront.shopfront
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
Darkswarm.controller "ProducersTabCtrl", ($scope, CurrentHub, Enterprises, EnterpriseModal) ->
|
||||
# Injecting Enterprises so CurrentHub.producers is dereferenced.
|
||||
# We should probably dereference here instead and separate out CurrentHub dereferencing from the Enterprise factory.
|
||||
$scope.CurrentHub = CurrentHub
|
||||
Darkswarm.controller "ProducersTabCtrl", ($scope, Shopfront, EnterpriseModal) ->
|
||||
$scope.shopfront = Shopfront.shopfront
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
Darkswarm.directive "enterpriseModal", ($modal, Enterprises, EnterpriseResource) ->
|
||||
Darkswarm.directive "enterpriseModal", (EnterpriseModal) ->
|
||||
restrict: 'E'
|
||||
replace: true
|
||||
template: "<a ng-transclude></a>"
|
||||
transclude: true
|
||||
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)
|
||||
elem.on "click", (event) =>
|
||||
event.stopPropagation()
|
||||
|
||||
scope.modalInstance = EnterpriseModal.open scope.enterprise
|
||||
@@ -1,18 +1,21 @@
|
||||
Darkswarm.factory 'Enterprises', (enterprises, CurrentHub, Taxons, Dereferencer, visibleFilter, Matcher, Geo, $rootScope) ->
|
||||
Darkswarm.factory 'Enterprises', (enterprises, CurrentHub, Taxons, Dereferencer, Matcher, Geo, $rootScope) ->
|
||||
new class Enterprises
|
||||
enterprises_by_id: {}
|
||||
|
||||
constructor: ->
|
||||
# Populate Enterprises.enterprises from json in page.
|
||||
@enterprises = enterprises
|
||||
|
||||
# Map enterprises to id/object pairs for lookup.
|
||||
for enterprise in enterprises
|
||||
@enterprises_by_id[enterprise.id] = enterprise
|
||||
|
||||
# Replace enterprise and taxons ids with actual objects.
|
||||
@dereferenceEnterprises()
|
||||
@visible_enterprises = visibleFilter @enterprises
|
||||
@producers = @visible_enterprises.filter (enterprise)->
|
||||
|
||||
@producers = @enterprises.filter (enterprise)->
|
||||
enterprise.category in ["producer_hub", "producer_shop", "producer"]
|
||||
@hubs = @visible_enterprises.filter (enterprise)->
|
||||
@hubs = @enterprises.filter (enterprise)->
|
||||
enterprise.category in ["hub", "hub_profile", "producer_hub", "producer_shop"]
|
||||
|
||||
dereferenceEnterprises: ->
|
||||
@@ -22,8 +25,6 @@ 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)
|
||||
|
||||
|
||||
@@ -1,14 +1,3 @@
|
||||
Darkswarm.factory 'Groups', (groups, Enterprises, Dereferencer) ->
|
||||
Darkswarm.factory 'Groups', (groups) ->
|
||||
new class Groups
|
||||
groups: groups
|
||||
groups_by_id: {}
|
||||
constructor: ->
|
||||
for group in @groups
|
||||
@groups_by_id[group.id] = group
|
||||
@dereference()
|
||||
dereference: ->
|
||||
for group in @groups
|
||||
Dereferencer.dereference group.enterprises, Enterprises.enterprises_by_id
|
||||
for enterprise in Enterprises.enterprises
|
||||
Dereferencer.dereference enterprise.groups, @groups_by_id
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Darkswarm.factory "OfnMap", (Enterprises, EnterpriseModal, visibleFilter) ->
|
||||
Darkswarm.factory "OfnMap", (Enterprises, EnterpriseModal) ->
|
||||
new class OfnMap
|
||||
constructor: ->
|
||||
@enterprises = @enterprise_markers(Enterprises.enterprises)
|
||||
@@ -6,7 +6,7 @@ Darkswarm.factory "OfnMap", (Enterprises, EnterpriseModal, visibleFilter) ->
|
||||
enterprise.latitude != null || enterprise.longitude != null # Remove enterprises w/o lat or long
|
||||
|
||||
enterprise_markers: (enterprises) ->
|
||||
@extend(enterprise) for enterprise in visibleFilter(enterprises)
|
||||
@extend(enterprise) for enterprise in enterprises
|
||||
|
||||
# Adding methods to each enterprise
|
||||
extend: (enterprise) ->
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Darkswarm.factory 'Products', ($resource, Enterprises, Dereferencer, Taxons, Properties, Cart, Variants) ->
|
||||
Darkswarm.factory 'Products', ($resource, Shopfront, Dereferencer, Taxons, Properties, Cart, Variants) ->
|
||||
new class Products
|
||||
constructor: ->
|
||||
@update()
|
||||
@@ -31,7 +31,7 @@ Darkswarm.factory 'Products', ($resource, Enterprises, Dereferencer, Taxons, Pro
|
||||
|
||||
dereference: ->
|
||||
for product in @products
|
||||
product.supplier = Enterprises.enterprises_by_id[product.supplier.id]
|
||||
product.supplier = Shopfront.producers_by_id[product.supplier.id]
|
||||
Dereferencer.dereference product.taxons, Taxons.taxons_by_id
|
||||
|
||||
product.properties = angular.copy(product.properties_with_values)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
Darkswarm.factory 'Shopfront', (shopfront) ->
|
||||
new class Shopfront
|
||||
shopfront: shopfront
|
||||
producers_by_id: {}
|
||||
|
||||
constructor: ->
|
||||
for producer in shopfront.producers
|
||||
@producers_by_id[producer.id] = producer
|
||||
@@ -4,6 +4,7 @@ class EnterprisesController < BaseController
|
||||
layout "darkswarm"
|
||||
helper Spree::ProductsHelper
|
||||
include OrderCyclesHelper
|
||||
include SerializerHelper
|
||||
|
||||
# These prepended filters are in the reverse order of execution
|
||||
prepend_before_filter :set_order_cycles, :require_distributor_chosen, :reset_order, only: :shop
|
||||
@@ -17,15 +18,7 @@ class EnterprisesController < BaseController
|
||||
return redirect_to main_app.cart_path unless enough_stock?
|
||||
set_noindex_meta_tag
|
||||
|
||||
enterprises = current_distributor
|
||||
.plus_relatives_and_oc_producers(shop_order_cycles)
|
||||
.activated
|
||||
.includes(address: :state)
|
||||
.all
|
||||
|
||||
enterprises = inject_json_ams('enterprises', enterprises)
|
||||
|
||||
render locals: { enterprises: enterprises }
|
||||
@enterprise = current_distributor
|
||||
end
|
||||
|
||||
def relatives
|
||||
@@ -111,14 +104,4 @@ class EnterprisesController < BaseController
|
||||
def set_noindex_meta_tag
|
||||
@noindex_meta_tag = true unless current_distributor.visible?
|
||||
end
|
||||
|
||||
def inject_json_ams(name, object)
|
||||
options = {
|
||||
each_serializer: Api::EnterpriseSerializer,
|
||||
data: OpenFoodNetwork::EnterpriseInjectionData.new
|
||||
}
|
||||
serializer_instance = ActiveModel::ArraySerializer.new(object, options)
|
||||
|
||||
{ name: name, json: serializer_instance.to_json }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
class GroupsController < BaseController
|
||||
layout 'darkswarm'
|
||||
|
||||
def index
|
||||
@groups = EnterpriseGroup.on_front_page.by_position
|
||||
end
|
||||
|
||||
def show
|
||||
enable_embedded_shopfront
|
||||
@hide_menu = true if @shopfront_layout == 'embedded'
|
||||
|
||||
@@ -3,5 +3,14 @@ class ProducersController < BaseController
|
||||
|
||||
before_filter :enable_embedded_shopfront
|
||||
|
||||
def index; end
|
||||
def index
|
||||
@enterprises = Enterprise
|
||||
.activated
|
||||
.visible
|
||||
.is_primary_producer
|
||||
.includes(address: :state)
|
||||
.includes(:properties)
|
||||
.includes(supplied_products: :properties)
|
||||
.all
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,6 +6,8 @@ class ShopsController < BaseController
|
||||
def index
|
||||
@enterprises = Enterprise
|
||||
.activated
|
||||
.visible
|
||||
.is_distributor
|
||||
.includes(address: :state)
|
||||
.includes(:properties)
|
||||
.includes(supplied_products: :properties)
|
||||
|
||||
@@ -1,19 +1,41 @@
|
||||
require 'open_food_network/enterprise_injection_data'
|
||||
|
||||
module InjectionHelper
|
||||
include SerializerHelper
|
||||
|
||||
def inject_enterprises(enterprises = Enterprise.activated.includes(address: :state).all)
|
||||
inject_json_ams(
|
||||
'enterprises',
|
||||
"enterprises",
|
||||
enterprises,
|
||||
Api::EnterpriseSerializer,
|
||||
enterprise_injection_data
|
||||
)
|
||||
end
|
||||
|
||||
def inject_enterprise_shopfront_list
|
||||
def inject_groups
|
||||
select_only = required_attributes EnterpriseGroup, Api::GroupListSerializer
|
||||
|
||||
inject_json_ams(
|
||||
'enterprises',
|
||||
Enterprise.activated.includes(address: :state).all,
|
||||
"groups",
|
||||
EnterpriseGroup.on_front_page.by_position.select(select_only).includes(address: :state).all,
|
||||
Api::GroupListSerializer
|
||||
)
|
||||
end
|
||||
|
||||
def inject_enterprise_shopfront(enterprise)
|
||||
inject_json_ams(
|
||||
"shopfront",
|
||||
enterprise,
|
||||
Api::EnterpriseShopfrontSerializer
|
||||
)
|
||||
end
|
||||
|
||||
def inject_enterprise_shopfront_list
|
||||
select_only = required_attributes Enterprise, Api::EnterpriseShopfrontListSerializer
|
||||
|
||||
inject_json_ams(
|
||||
"enterprises",
|
||||
Enterprise.activated.visible.select(select_only).includes(address: :state).all,
|
||||
Api::EnterpriseShopfrontListSerializer
|
||||
)
|
||||
end
|
||||
@@ -23,7 +45,12 @@ module InjectionHelper
|
||||
end
|
||||
|
||||
def inject_group_enterprises
|
||||
inject_json_ams "group_enterprises", @group.enterprises.activated.all, Api::EnterpriseSerializer, enterprise_injection_data
|
||||
inject_json_ams(
|
||||
"enterprises",
|
||||
@group.enterprises.activated.all,
|
||||
Api::EnterpriseSerializer,
|
||||
enterprise_injection_data
|
||||
)
|
||||
end
|
||||
|
||||
def inject_current_hub
|
||||
@@ -79,11 +106,7 @@ module InjectionHelper
|
||||
end
|
||||
|
||||
def inject_saved_credit_cards
|
||||
data = if spree_current_user
|
||||
spree_current_user.credit_cards.with_payment_profile.all
|
||||
else
|
||||
[]
|
||||
end
|
||||
data = spree_current_user ? spree_current_user.credit_cards.with_payment_profile.all : []
|
||||
|
||||
inject_json_ams "savedCreditCards", data, Api::CreditCardSerializer
|
||||
end
|
||||
|
||||
@@ -3,4 +3,13 @@ module SerializerHelper
|
||||
return [] if ids.blank?
|
||||
ids.map { |id| { id: id } }
|
||||
end
|
||||
|
||||
# Returns an array of the fields a serializer needs from it's object
|
||||
# so we can #select only what the serializer will actually use
|
||||
def required_attributes(model, serializer)
|
||||
model_attributes = model.attribute_names
|
||||
serializer_attributes = serializer._attributes.keys.map(&:to_s)
|
||||
|
||||
(serializer_attributes & model_attributes).map { |attr| "#{model.table_name}.#{attr}" }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -322,6 +322,14 @@ class Enterprise < ActiveRecord::Base
|
||||
select('DISTINCT spree_taxons.*')
|
||||
end
|
||||
|
||||
def current_distributed_taxons
|
||||
Spree::Taxon
|
||||
.select("DISTINCT spree_taxons.*")
|
||||
.joins(products: :variants_including_master)
|
||||
.joins("INNER JOIN (#{current_exchange_variants.to_sql}) \
|
||||
AS exchange_variants ON spree_variants.id = exchange_variants.variant_id")
|
||||
end
|
||||
|
||||
# Return all taxons for all supplied products
|
||||
def supplied_taxons
|
||||
Spree::Taxon.
|
||||
@@ -367,6 +375,14 @@ class Enterprise < ActiveRecord::Base
|
||||
|
||||
private
|
||||
|
||||
def current_exchange_variants
|
||||
ExchangeVariant.joins(exchange: :order_cycle)
|
||||
.merge(Exchange.outgoing)
|
||||
.select("DISTINCT exchange_variants.variant_id, exchanges.receiver_id AS enterprise_id")
|
||||
.where("exchanges.receiver_id = ?", id)
|
||||
.merge(OrderCycle.active.with_distributor(id))
|
||||
end
|
||||
|
||||
def name_is_unique
|
||||
dups = Enterprise.where(name: name)
|
||||
dups = dups.where('id != ?', id) unless new_record?
|
||||
|
||||
@@ -14,7 +14,7 @@ module Api
|
||||
:long_description, :website, :instagram, :linkedin, :twitter,
|
||||
:facebook, :is_primary_producer, :is_distributor, :phone, :visible,
|
||||
:email_address, :hash, :logo, :promo_image, :path, :pickup, :delivery,
|
||||
:icon, :icon_font, :producer_icon_font, :category, :producers, :hubs
|
||||
:icon, :icon_font, :producer_icon_font, :category
|
||||
|
||||
attributes :taxons, :supplied_taxons
|
||||
|
||||
@@ -53,16 +53,6 @@ module Api
|
||||
enterprise_shop_path(enterprise)
|
||||
end
|
||||
|
||||
def producers
|
||||
relatives = data.relatives[enterprise.id]
|
||||
ids_to_objs(relatives.andand[:producers])
|
||||
end
|
||||
|
||||
def hubs
|
||||
relatives = data.relatives[enterprise.id]
|
||||
ids_to_objs(relatives.andand[:distributors])
|
||||
end
|
||||
|
||||
def taxons
|
||||
if active
|
||||
ids_to_objs data.current_distributed_taxons[enterprise.id]
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
module Api
|
||||
class EnterpriseShopfrontListSerializer < ActiveModel::Serializer
|
||||
attributes :name, :id, :latitude, :longitude, :is_primary_producer, :is_distributor,
|
||||
:visible, :path, :icon, :icon_font, :producer_icon_font
|
||||
:path, :icon, :icon_font, :producer_icon_font, :address_id, :sells,
|
||||
:permalink
|
||||
|
||||
has_one :address, serializer: Api::AddressSerializer
|
||||
|
||||
|
||||
@@ -51,7 +51,10 @@ module Api
|
||||
|
||||
def producers
|
||||
ActiveModel::ArraySerializer.new(
|
||||
enterprise.suppliers, each_serializer: Api::EnterpriseThinSerializer
|
||||
enterprise.plus_relatives_and_oc_producers(
|
||||
OrderCycle.not_closed.with_distributor(enterprise)
|
||||
),
|
||||
each_serializer: Api::EnterpriseThinSerializer
|
||||
)
|
||||
end
|
||||
|
||||
@@ -62,8 +65,10 @@ module Api
|
||||
end
|
||||
|
||||
def taxons
|
||||
taxons = active ? enterprise.current_distributed_taxons : enterprise.distributed_taxons
|
||||
|
||||
ActiveModel::ArraySerializer.new(
|
||||
enterprise.distributed_taxons, each_serializer: Api::TaxonSerializer
|
||||
taxons, each_serializer: Api::TaxonSerializer
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
16
app/serializers/api/group_list_serializer.rb
Normal file
16
app/serializers/api/group_list_serializer.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
module Api
|
||||
class GroupListSerializer < ActiveModel::Serializer
|
||||
attributes :id, :name, :permalink, :email, :website, :facebook, :instagram,
|
||||
:linkedin, :twitter, :enterprises, :state, :address_id
|
||||
|
||||
def state
|
||||
object.address.state.abbr
|
||||
end
|
||||
|
||||
def enterprises
|
||||
ActiveModel::ArraySerializer.new(
|
||||
object.enterprises, each_serializer: Api::EnterpriseThinSerializer
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -5,7 +5,7 @@
|
||||
- content_for(:image) do
|
||||
= current_distributor.logo.url
|
||||
|
||||
= render partial: 'json/injection_ams', locals: enterprises
|
||||
= inject_enterprise_shopfront(@enterprise)
|
||||
|
||||
%shop.darkswarm
|
||||
- if @shopfront_layout == 'embedded'
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
- content_for(:title) do
|
||||
= t :groups_title
|
||||
|
||||
= inject_enterprises
|
||||
|
||||
:javascript
|
||||
angular.module('Darkswarm').value('groups', #{render partial: "json/groups", object: @groups})
|
||||
= inject_groups
|
||||
|
||||
#groups.pad-top.footer-pad{"ng-controller" => "GroupsCtrl"}
|
||||
.row
|
||||
|
||||
@@ -5,12 +5,6 @@
|
||||
- content_for(:image) do
|
||||
= @group.logo.url
|
||||
|
||||
-# inject all enterprises as "enterprises"
|
||||
-# it could be more efficient to inject only the enterprises that are related to the group
|
||||
= inject_enterprises
|
||||
|
||||
-# inject enterprises in this group
|
||||
-# further hubs and producers of these enterprises can't be resolved within this small subset
|
||||
= inject_group_enterprises
|
||||
|
||||
#group-page.row.pad-top.footer-pad{"ng-controller" => "GroupPageCtrl"}
|
||||
@@ -68,8 +62,8 @@
|
||||
.small-12.columns
|
||||
.active_table
|
||||
%producer.active_table_node.row.animate-repeat{id: "{{producer.path}}",
|
||||
"ng-repeat" => "producer in filteredEnterprises = (group_producers | searchEnterprises:query | taxons:activeTaxons | properties:activeProperties:'supplied_properties')",
|
||||
"ng-controller" => "GroupEnterpriseNodeCtrl",
|
||||
"ng-repeat" => "producer in filteredEnterprises = (Enterprises.producers | searchEnterprises:query | taxons:activeTaxons | properties:activeProperties:'supplied_properties')",
|
||||
"ng-controller" => "ProducerNodeCtrl",
|
||||
"ng-class" => "{'closed' : !open(), 'open' : open(), 'inactive' : !producer.active}",
|
||||
id: "{{producer.hash}}"}
|
||||
|
||||
@@ -89,15 +83,15 @@
|
||||
= t :groups_hubs
|
||||
|
||||
= render "shared/components/enterprise_search"
|
||||
= render "shops/filters", resource: "group_hubs", property_filters: "| searchEnterprises:query | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles"
|
||||
= render "shops/filters", resource: "Enterprises.hubs", property_filters: "| searchEnterprises:query | taxons:activeTaxons | shipping:shippingTypes"
|
||||
|
||||
.row
|
||||
.small-12.columns
|
||||
.active_table
|
||||
%hub.active_table_node.row.animate-repeat{id: "{{hub.hash}}",
|
||||
"ng-repeat" => "hub in filteredEnterprises = (group_hubs | searchEnterprises:query | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles | properties:activeProperties:'distributed_properties' | orderBy:['-active', '+orders_close_at'])",
|
||||
"ng-repeat" => "hub in filteredEnterprises = (Enterprises.hubs | searchEnterprises:query | taxons:activeTaxons | shipping:shippingTypes | properties:activeProperties:'distributed_properties' | orderBy:['-active', '+orders_close_at'])",
|
||||
"ng-class" => "{'is_profile' : hub.category == 'hub_profile', 'closed' : !open(), 'open' : open(), 'inactive' : !hub.active, 'current' : current()}",
|
||||
"ng-controller" => "GroupEnterpriseNodeCtrl"}
|
||||
"ng-controller" => "HubNodeCtrl"}
|
||||
.small-12.columns
|
||||
= render 'shops/skinny'
|
||||
= render 'shops/fat'
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
.row.active_table_row{"ng-if" => "open()", "ng-click" => "toggle($event)", "ng-class" => "{'open' : open()}"}
|
||||
.columns.small-12.fat.text-center{"ng-show" => "open() && shopfront_loading"}
|
||||
%p
|
||||
%img.spinner.text-center{ src: "/assets/spinning-circles.svg" }
|
||||
|
||||
.columns.small-12.medium-7.large-7.fat
|
||||
.columns.small-12.medium-7.large-7.fat{"ng-show" => "open() && !shopfront_loading"}
|
||||
/ Will add in long description available once clean up HTML formatting producer.long_description
|
||||
%div{"ng-if" => "::producer.description"}
|
||||
%label
|
||||
@@ -11,7 +14,7 @@
|
||||
%label
|
||||
%img.right.show-for-medium-up{"ng-src" => "{{::producer.logo}}" }
|
||||
|
||||
.columns.small-12.medium-5.large-5.fat
|
||||
.columns.small-12.medium-5.large-5.fat{"ng-show" => "open() && !shopfront_loading"}
|
||||
|
||||
%div{"ng-if" => "::producer.supplied_taxons"}
|
||||
%label
|
||||
@@ -64,8 +67,8 @@
|
||||
%a{"ng-href" => "http://instagram.com/{{::producer.instagram}}", target: "_blank"}
|
||||
%i.ofn-i_043-instagram
|
||||
|
||||
.row.active_table_row.pad-top{"ng-if" => "open() && producer.hubs"}
|
||||
.columns.small-12
|
||||
.row.active_table_row.pad-top{"ng-if" => "open() && producer.hubs && !shopfront_loading"}
|
||||
.columns.small-12{"ng-if" => "producer.hubs.length > 0"}
|
||||
.row
|
||||
.columns.small-12.fat
|
||||
%div{"ng-if" => "::producer.name"}
|
||||
@@ -75,8 +78,8 @@
|
||||
|
||||
.row.cta-container
|
||||
.columns.small-12
|
||||
%a.cta-hub{"ng-repeat" => "hub in producer.hubs | visible | orderBy:'-active'",
|
||||
"ng-href" => "{{::hub.path}}", "ng-attr-target" => "{{ embedded_layout ? '_blank' : undefined }}", "ofn-change-hub" => "hub",
|
||||
%a.cta-hub{"ng-repeat" => "hub in producer.hubs | orderBy:'-active'",
|
||||
"ng-href" => "{{::hub.path}}", "ng-attr-target" => "{{ embedded_layout ? '_blank' : undefined }}",
|
||||
"ng-class" => "::{primary: hub.active, secondary: !hub.active}"}
|
||||
%i.ofn-i_068-shop-reversed{"ng-if" => "::hub.active"}
|
||||
%i.ofn-i_068-shop-reversed{"ng-if" => "::!hub.active"}
|
||||
|
||||
@@ -11,13 +11,13 @@
|
||||
.light
|
||||
= t :producers_filter
|
||||
= t :producers_filter_type
|
||||
%filter-selector.small-block-grid-2.medium-block-grid-4.large-block-grid-6{"selector-set" => "filterSelectors", objects: "producers_to_filter | searchEnterprises:query | taxonsOf", "active-selectors" => "activeTaxons"}
|
||||
%filter-selector.small-block-grid-2.medium-block-grid-4.large-block-grid-6{"selector-set" => "filterSelectors", objects: "Enterprises.producers | searchEnterprises:query | taxonsOf", "active-selectors" => "activeTaxons"}
|
||||
|
||||
%h5.tdhead
|
||||
.light
|
||||
= t :producers_filter
|
||||
= t :producers_filter_property
|
||||
.filter-shopfront.property-selectors
|
||||
%filter-selector{ "selector-set" => "filterSelectors", objects: "producers_to_filter | searchEnterprises:query | taxons:activeTaxons | propertiesOf:'supplied_properties'", "active-selectors" => "activeProperties"}
|
||||
%filter-selector{ "selector-set" => "filterSelectors", objects: "Enterprises.producers | searchEnterprises:query | taxons:activeTaxons | propertiesOf:'supplied_properties'", "active-selectors" => "activeProperties"}
|
||||
|
||||
= render partial: 'shared/components/filter_box'
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
.row.active_table_row{"ng-click" => "toggle($event)", "ng-class" => "{'closed' : !open(), 'is_distributor' : producer.is_distributor}"}
|
||||
.columns.small-12.medium-8.large-8.skinny-head
|
||||
.columns.small-12.medium-7.large-7.skinny-head
|
||||
%span{"ng-if" => "::producer.is_distributor" }
|
||||
%a.is_distributor{"ng-href" => "{{::producer.path}}", "ng-attr-target" => "{{ embedded_layout ? '_blank' : undefined}}"}
|
||||
.row.vertical-align-middle
|
||||
.columns.small-2.medium-2.large-2
|
||||
.row.vertical-align-middle
|
||||
.columns.small-12
|
||||
%a.is_distributor{"ng-href" => "{{::producer.path}}", "ng-attr-target" => "{{ embedded_layout ? '_blank' : undefined}}", "data-is-link" => "true"}
|
||||
%i{ng: {class: "::producer.producer_icon_font"}}
|
||||
.columns.small-10.medium-10.large-10
|
||||
%span.margin-top
|
||||
%strong{"ng-bind" => "::producer.name"}
|
||||
|
||||
%span.producer-name{"ng-if" => "::!producer.is_distributor" }
|
||||
.row.vertical-align-middle
|
||||
.columns.small-2.medium-2.large-2
|
||||
.columns.small-12
|
||||
%i{ng: {class: "::producer.producer_icon_font"}}
|
||||
.columns.small-10.medium-10.large-10
|
||||
%span.margin-top
|
||||
%strong{"ng-bind" => "::producer.name"}
|
||||
.columns.small-6.medium-2.large-2
|
||||
|
||||
.columns.small-6.medium-3.large-3
|
||||
%span.margin-top{"ng-bind" => "::producer.address.city"}
|
||||
|
||||
.columns.small-4.medium-1.large-1
|
||||
%span.margin-top{"ng-bind" => "::producer.address.state_name"}
|
||||
|
||||
.columns.small-2.medium-1.large-1.text-right
|
||||
%span.margin-top
|
||||
%i{"ng-class" => "{'ofn-i_005-caret-down' : !open(), 'ofn-i_006-caret-up' : open()}"}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
- content_for(:title) do
|
||||
= t :producers_title
|
||||
|
||||
= inject_enterprises
|
||||
= inject_enterprises(@enterprises)
|
||||
|
||||
.producers{"ng-controller" => "EnterprisesCtrl", "ng-cloak" => true}
|
||||
.row
|
||||
@@ -16,7 +16,7 @@
|
||||
.small-12.columns
|
||||
.active_table
|
||||
%producer.active_table_node.row.animate-repeat{id: "{{producer.path}}",
|
||||
"ng-repeat" => "producer in filteredEnterprises = (Enterprises.producers | visible | searchEnterprises:query | taxons:activeTaxons | properties:activeProperties:'supplied_properties')",
|
||||
"ng-repeat" => "producer in filteredEnterprises = (Enterprises.producers | searchEnterprises:query | taxons:activeTaxons | properties:activeProperties:'supplied_properties')",
|
||||
"ng-controller" => "ProducerNodeCtrl",
|
||||
"ng-class" => "{'closed' : !open(), 'open' : open(), 'inactive' : !producer.active}",
|
||||
id: "{{producer.hash}}"}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
.small-12.medium-6.columns.text-right
|
||||
.profile-checkbox
|
||||
%button.button.secondary.tiny.right.help-btn.ng-scope{:popover => t(:components_profiles_popover, sitename: Spree::Config[:site_name]), "popover-placement" => "left"}><
|
||||
%i.ofn-i_013-help
|
||||
%label
|
||||
%input{"ng-model" => "show_profiles", type: "checkbox", name: "profile"}
|
||||
= t :components_profiles_show
|
||||
@@ -3,7 +3,7 @@
|
||||
.panel
|
||||
.row
|
||||
.small-12.large-8.columns
|
||||
%img.hero-img-small{"ng-src" => "{{::CurrentHub.hub.promo_image}}", "ng-if" => "::CurrentHub.hub.promo_image"}
|
||||
%p{"ng-bind-html" => "::CurrentHub.hub.long_description"}
|
||||
%img.hero-img-small{"ng-src" => "{{::shopfront.promo_image}}", "ng-if" => "::shopfront.promo_image"}
|
||||
%p{"ng-bind-html" => "::shopfront.long_description"}
|
||||
.small-12.large-4.columns
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
.row
|
||||
.small-12.columns
|
||||
%h5
|
||||
= t :shopping_producers_of_hub, hub: '{{CurrentHub.hub.name}}'
|
||||
= t :shopping_producers_of_hub, hub: '{{ shopfront.name }}'
|
||||
%ul.small-block-grid-2.large-block-grid-4
|
||||
%li{"ng-repeat" => "enterprise in CurrentHub.hub.producers"}
|
||||
%li{"ng-repeat" => "enterprise in shopfront.producers"}
|
||||
%enterprise-modal
|
||||
%i.ofn-i_036-producers
|
||||
{{ enterprise.name }}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
.row.active_table_row{"ng-show" => "open()", "ng-click" => "toggle($event)", "ng-class" => "{'open' : open()}"}
|
||||
.columns.small-12.medium-6.large-5.fat
|
||||
.columns.small-12.fat.text-center{"ng-show" => "open() && shopfront_loading"}
|
||||
%p
|
||||
%img.spinner.text-center{ src: "/assets/spinning-circles.svg" }
|
||||
|
||||
.columns.small-12.medium-6.large-5.fat{"ng-show" => "open() && !shopfront_loading"}
|
||||
%div{"ng-if" => "::hub.taxons"}
|
||||
%label
|
||||
= t :hubs_buy
|
||||
@@ -13,7 +17,7 @@
|
||||
%span{"ng-bind" => "property.presentation"}
|
||||
%div.show-for-medium-up{"ng-if" => "::hub.taxons.length==0"}
|
||||
|
||||
.columns.small-12.medium-3.large-2.fat
|
||||
.columns.small-12.medium-3.large-2.fat{"ng-show" => "open() && !shopfront_loading"}
|
||||
%div{"ng-if" => "::(hub.pickup || hub.delivery)"}
|
||||
%label
|
||||
= t :hubs_delivery_options
|
||||
@@ -24,7 +28,7 @@
|
||||
%li.delivery{"ng-if" => "::hub.delivery"}
|
||||
%i.ofn-i_039-delivery
|
||||
= t :hubs_delivery
|
||||
.columns.small-12.medium-3.large-5.fat
|
||||
.columns.small-12.medium-3.large-5.fat{"ng-show" => "open() && !shopfront_loading"}
|
||||
%div{"ng-if" => "::hub.producers"}
|
||||
%label
|
||||
= t :hubs_producers
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
- resource ||= "visibleMatches"
|
||||
- property_filters ||= "| closedShops:show_closed | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles"
|
||||
- property_filters ||= "| closedShops:show_closed | taxons:activeTaxons | shipping:shippingTypes"
|
||||
|
||||
.row
|
||||
= render 'shared/components/filter_controls'
|
||||
-# .small-12.medium-6.columns
|
||||
= render 'shared/components/show_profiles'
|
||||
|
||||
.row.animate-show.filter-row{"ng-show" => "filtersActive"}
|
||||
.small-12.columns
|
||||
@@ -15,7 +13,7 @@
|
||||
= t :hubs_filter_by
|
||||
= t :hubs_filter_type
|
||||
|
||||
%filter-selector.small-block-grid-2.medium-block-grid-4.large-block-grid-5{ "selector-set" => "filterSelectors", objects: "#{resource} | visible | taxonsOf", "active-selectors" => "activeTaxons" }
|
||||
%filter-selector.small-block-grid-2.medium-block-grid-4.large-block-grid-5{ "selector-set" => "filterSelectors", objects: "#{resource} | taxonsOf", "active-selectors" => "activeTaxons" }
|
||||
.small-12.large-3.columns
|
||||
%h5.tdhead
|
||||
.light
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
= inject_enterprises(@enterprises)
|
||||
|
||||
#hubs.hubs{"ng-controller" => "EnterprisesCtrl", "ng-cloak" => true}
|
||||
.row
|
||||
.small-12.columns
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.active_table
|
||||
%hub.active_table_node.row{"ng-repeat" => "hub in #{enterprises}Filtered = (#{enterprises} | closedShops:show_closed | taxons:activeTaxons | properties:activeProperties:'distributed_properties' | shipping:shippingTypes | showHubProfiles:show_profiles | orderBy:['-active', '+distance', '+orders_close_at'])",
|
||||
%hub.active_table_node.row{"ng-repeat" => "hub in #{enterprises}Filtered = (#{enterprises} | closedShops:show_closed | taxons:activeTaxons | properties:activeProperties:'distributed_properties' | shipping:shippingTypes | orderBy:['-active', '+distance', '+orders_close_at'])",
|
||||
"ng-class" => "{'is_profile' : hub.category == 'hub_profile', 'closed' : !open(), 'open' : open(), 'inactive' : !hub.active, 'current' : current()}",
|
||||
"ng-controller" => "HubNodeCtrl",
|
||||
id: "{{hub.hash}}"}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
- content_for(:title) do
|
||||
= t :shops_title
|
||||
|
||||
= inject_enterprises(@enterprises)
|
||||
|
||||
#panes
|
||||
#shops.pane
|
||||
.row
|
||||
|
||||
@@ -12,10 +12,6 @@ module OpenFoodNetwork
|
||||
@shipping_method_services ||= Spree::ShippingMethod.services
|
||||
end
|
||||
|
||||
def relatives
|
||||
@relatives ||= EnterpriseRelationship.relatives(true)
|
||||
end
|
||||
|
||||
def supplied_taxons
|
||||
@supplied_taxons ||= Spree::Taxon.supplied_taxons
|
||||
end
|
||||
|
||||
@@ -2,13 +2,9 @@ require 'spec_helper'
|
||||
|
||||
describe GroupsController, type: :controller do
|
||||
render_views
|
||||
let(:enterprise) { create(:distributor_enterprise) }
|
||||
|
||||
let!(:enterprise) { create(:distributor_enterprise) }
|
||||
let!(:group) { create(:enterprise_group, enterprises: [enterprise], on_front_page: true) }
|
||||
it "gets all visible groups" do
|
||||
allow(EnterpriseGroup).to receive_message_chain :on_front_page, :by_position
|
||||
expect(EnterpriseGroup).to receive :on_front_page
|
||||
get :index
|
||||
end
|
||||
|
||||
it "loads all enterprises for group" do
|
||||
get :index
|
||||
|
||||
@@ -1,21 +1,15 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe ShopsController, type: :controller do
|
||||
include WebHelper
|
||||
render_views
|
||||
|
||||
let!(:distributor) { create(:distributor_enterprise) }
|
||||
let!(:invisible_distributor) { create(:distributor_enterprise, visible: false) }
|
||||
|
||||
before do
|
||||
allow(Enterprise).to receive_message_chain(:distributors_with_active_order_cycles, :ready_for_checkout) { [distributor] }
|
||||
end
|
||||
|
||||
# Exclusion from actual rendered view handled in features/consumer/home
|
||||
it "shows JSON for invisible hubs" do
|
||||
get :index
|
||||
expect(response.body).to have_content(invisible_distributor.name)
|
||||
end
|
||||
|
||||
it 'renders distributed product properties' do
|
||||
product_property = create(:property, presentation: 'eggs')
|
||||
product = create(:product, properties: [product_property])
|
||||
|
||||
@@ -5,6 +5,7 @@ feature '
|
||||
I want to see a list of producers
|
||||
So that I can shop at hubs distributing their products
|
||||
', js: true do
|
||||
include AuthenticationWorkflow
|
||||
include WebHelper
|
||||
include UIComponentHelper
|
||||
|
||||
@@ -21,6 +22,10 @@ feature '
|
||||
let(:shop) { create(:distributor_enterprise) }
|
||||
let!(:er) { create(:enterprise_relationship, parent: shop, child: producer1) }
|
||||
|
||||
before :each do
|
||||
use_api_as_unauthenticated_user
|
||||
end
|
||||
|
||||
before do
|
||||
product1.set_property 'Organic', 'NASAA 12345'
|
||||
product2.set_property 'Biodynamic', 'ABC123'
|
||||
@@ -79,8 +84,8 @@ feature '
|
||||
page.should have_content 'Fruit'
|
||||
|
||||
# -- Properties
|
||||
page.should have_content 'Organic' # Product property
|
||||
page.should have_content 'Local' # Producer property
|
||||
expect(page).to have_content 'Organic' # Product property
|
||||
expect(page).to have_content 'Local' # Producer property
|
||||
end
|
||||
|
||||
it "doesn't show invisible producers" do
|
||||
@@ -89,7 +94,7 @@ feature '
|
||||
|
||||
it "links to places to buy produce" do
|
||||
expand_active_table_node producer1.name
|
||||
page.should have_link shop.name
|
||||
expect(page).to have_link shop.name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,6 +3,7 @@ require 'spec_helper'
|
||||
feature 'Shops', js: true do
|
||||
include AuthenticationWorkflow
|
||||
include UIComponentHelper
|
||||
include WebHelper
|
||||
|
||||
let!(:distributor) { create(:distributor_enterprise, with_payment_and_shipping: true) }
|
||||
let!(:invisible_distributor) { create(:distributor_enterprise, visible: false) }
|
||||
@@ -13,6 +14,10 @@ feature 'Shops', js: true do
|
||||
let!(:producer) { create(:supplier_enterprise) }
|
||||
let!(:er) { create(:enterprise_relationship, parent: distributor, child: producer) }
|
||||
|
||||
before :each do
|
||||
use_api_as_unauthenticated_user
|
||||
end
|
||||
|
||||
before do
|
||||
producer.set_producer_property 'Organic', 'NASAA 12345'
|
||||
end
|
||||
@@ -55,21 +60,6 @@ feature 'Shops', js: true do
|
||||
follow_active_table_node distributor.name
|
||||
expect(page).to have_current_path enterprise_shop_path(distributor)
|
||||
end
|
||||
|
||||
describe "showing profiles" do
|
||||
before do
|
||||
check "Show profiles"
|
||||
end
|
||||
|
||||
it "still shows hubs" do
|
||||
expect(page).to have_content distributor.name
|
||||
end
|
||||
|
||||
# https://github.com/openfoodfoundation/openfoodnetwork/issues/1718
|
||||
it "shows profiles" do
|
||||
expect(page).to have_content profile.name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "showing available hubs" do
|
||||
|
||||
18
spec/helpers/serializer_helper_spec.rb
Normal file
18
spec/helpers/serializer_helper_spec.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe SerializerHelper, type: :helper do
|
||||
let(:serializer) do
|
||||
class ExampleEnterpriseSerializer < ActiveModel::Serializer
|
||||
attributes :id, :name
|
||||
end
|
||||
ExampleEnterpriseSerializer
|
||||
end
|
||||
|
||||
describe "#required_attributes" do
|
||||
it "returns only the attributes from the model that the serializer needs to be queried" do
|
||||
required_attributes = helper.required_attributes Enterprise, serializer
|
||||
|
||||
expect(required_attributes).to eq ['enterprises.id', 'enterprises.name']
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -20,11 +20,11 @@ describe "Enterprises service", ->
|
||||
{id: 1, visible: true, name: 'a', category: "hub", producers: [{id: 5}], taxons: [{id: 1}]},
|
||||
{id: 2, visible: true, name: 'b', category: "hub", producers: [{id: 6}]}
|
||||
{id: 3, visible: true, name: 'c', category: "hub_profile"}
|
||||
{id: 4, visible: false,name: 'd', category: "hub", producers: [{id: 7}]}
|
||||
{id: 4, visible: true, name: 'd', category: "hub", producers: [{id: 7}]}
|
||||
{id: 5, visible: true, name: 'e', category: "producer_hub", hubs: [{id: 1}]},
|
||||
{id: 6, visible: true, name: 'f', category: "producer_shop", hubs: [{id: 2}]},
|
||||
{id: 7, visible: true, name: 'g', category: "producer", hubs: [{id: 2}]}
|
||||
{id: 8, visible: false,name: 'h', category: "producer", hubs: [{id: 2}]}
|
||||
{id: 8, visible: true, name: 'h', category: "producer", hubs: [{id: 2}]}
|
||||
]
|
||||
H1: 0
|
||||
beforeEach ->
|
||||
@@ -49,10 +49,6 @@ describe "Enterprises service", ->
|
||||
it "puts the same objects in enterprises and enterprises_by_id", ->
|
||||
expect(Enterprises.enterprises[0]).toBe Enterprises.enterprises_by_id["1"]
|
||||
|
||||
it "dereferences references to other enterprises", ->
|
||||
expect(Enterprises.enterprises_by_id["1"].producers[0]).toBe enterprises[4]
|
||||
expect(Enterprises.enterprises_by_id["5"].hubs[0]).toBe enterprises[0]
|
||||
|
||||
it "dereferences taxons", ->
|
||||
expect(Enterprises.enterprises[0].taxons[0]).toBe taxons[0]
|
||||
|
||||
@@ -68,14 +64,6 @@ describe "Enterprises service", ->
|
||||
Enterprises.enterprises[4].active = false
|
||||
expect(Enterprises.producers[0].active).toBe false
|
||||
|
||||
it "only includes visible enterprises in hubs array", ->
|
||||
expect(Enterprises.hubs).toContain Enterprises.enterprises[0]
|
||||
expect(Enterprises.hubs).not.toContain Enterprises.enterprises[3]
|
||||
|
||||
it "only includes visible enterprises in producers array", ->
|
||||
expect(Enterprises.producers).toContain Enterprises.enterprises[4]
|
||||
expect(Enterprises.producers).not.toContain Enterprises.enterprises[7]
|
||||
|
||||
it "includes hub, hub_profile, producer_hub and, producer_shop enterprises in hubs array", ->
|
||||
expect(Enterprises.hubs).toContain Enterprises.enterprises[0]
|
||||
expect(Enterprises.hubs).toContain Enterprises.enterprises[2]
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
describe "Groups service", ->
|
||||
Groups = null
|
||||
Enterprises = null
|
||||
CurrentHubMock = {}
|
||||
Geo = {}
|
||||
groups = [{
|
||||
id: 1
|
||||
name: "Test Group"
|
||||
enterprises: [
|
||||
{id: 1},
|
||||
{id: 2}
|
||||
]
|
||||
}]
|
||||
enterprises = [
|
||||
{id: 1, name: "Test 1", groups: [{id: 1}]},
|
||||
{id: 2, name: "Test 2", groups: [{id: 1}]}
|
||||
]
|
||||
|
||||
beforeEach ->
|
||||
module 'Darkswarm'
|
||||
angular.module('Darkswarm').value('groups', groups)
|
||||
angular.module('Darkswarm').value('enterprises', enterprises)
|
||||
module ($provide)->
|
||||
$provide.value "CurrentHub", CurrentHubMock
|
||||
$provide.value "Geo", Geo
|
||||
null
|
||||
inject (_Groups_, _Enterprises_)->
|
||||
Groups = _Groups_
|
||||
Enterprises = _Enterprises_
|
||||
|
||||
it "dereferences group enterprises", ->
|
||||
expect(Groups.groups[0].enterprises[0]).toBe enterprises[0]
|
||||
|
||||
it "dereferences enterprise groups", ->
|
||||
expect(Enterprises.enterprises[0].groups[0]).toBe groups[0]
|
||||
@@ -1,10 +1,10 @@
|
||||
describe 'Products service', ->
|
||||
$httpBackend = null
|
||||
Products = null
|
||||
Enterprises = null
|
||||
Shopfront = null
|
||||
Variants = null
|
||||
Cart = null
|
||||
CurrentHubMock = {}
|
||||
shopfront = null
|
||||
currentOrder = null
|
||||
product = null
|
||||
productWithImage = null
|
||||
@@ -34,10 +34,14 @@ describe 'Products service', ->
|
||||
{ id: 1, name: "some property" }
|
||||
taxons =
|
||||
{ id: 2, name: "some taxon" }
|
||||
shopfront =
|
||||
producers:
|
||||
id: 9,
|
||||
name: "Test"
|
||||
|
||||
module 'Darkswarm'
|
||||
module ($provide)->
|
||||
$provide.value "CurrentHub", CurrentHubMock
|
||||
$provide.value "shopfront", shopfront
|
||||
$provide.value "currentOrder", currentOrder
|
||||
$provide.value "taxons", taxons
|
||||
$provide.value "properties", properties
|
||||
@@ -46,7 +50,7 @@ describe 'Products service', ->
|
||||
|
||||
inject ($injector, _$httpBackend_)->
|
||||
Products = $injector.get("Products")
|
||||
Enterprises = $injector.get("Enterprises")
|
||||
Shopfront = $injector.get("Shopfront")
|
||||
Properties = $injector.get("Properties")
|
||||
Variants = $injector.get("Variants")
|
||||
Cart = $injector.get("Cart")
|
||||
@@ -58,11 +62,11 @@ describe 'Products service', ->
|
||||
expect(Products.products[0].test).toEqual "cats"
|
||||
|
||||
it "dereferences suppliers", ->
|
||||
Enterprises.enterprises_by_id =
|
||||
Shopfront.producers_by_id =
|
||||
{id: 9, name: "test"}
|
||||
$httpBackend.expectGET("/shop/products").respond([{supplier : {id: 9}, master: {}}])
|
||||
$httpBackend.flush()
|
||||
expect(Products.products[0].supplier).toBe Enterprises.enterprises_by_id["9"]
|
||||
expect(Products.products[0].supplier).toBe Shopfront.producers_by_id["9"]
|
||||
|
||||
it "dereferences taxons", ->
|
||||
product.taxons = [2]
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
require 'spec_helper'
|
||||
|
||||
module OpenFoodNetwork
|
||||
describe EnterpriseInjectionData do
|
||||
describe "relatives" do
|
||||
let!(:enterprise) { create(:distributor_enterprise) }
|
||||
let!(:producer) { create(:supplier_enterprise) }
|
||||
let!(:producer_inactive) { create(:supplier_enterprise, sells: 'unspecified') }
|
||||
let!(:er_p) { create(:enterprise_relationship, parent: producer, child: enterprise) }
|
||||
let!(:er_pi) { create(:enterprise_relationship, parent: producer_inactive, child: enterprise) }
|
||||
|
||||
it "only loads activated relatives" do
|
||||
expect(subject.relatives[enterprise.id][:producers]).not_to include producer_inactive.id
|
||||
end
|
||||
|
||||
it "loads self where appropiate" do
|
||||
expect(subject.relatives[producer.id][:producers]).to include producer.id
|
||||
expect(subject.relatives[enterprise.id][:distributors]).to include enterprise.id
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -482,14 +482,26 @@ describe Enterprise do
|
||||
let(:supplier) { create(:supplier_enterprise) }
|
||||
let(:taxon1) { create(:taxon) }
|
||||
let(:taxon2) { create(:taxon) }
|
||||
let(:taxon3) { create(:taxon) }
|
||||
let(:product1) { create(:simple_product, primary_taxon: taxon1, taxons: [taxon1]) }
|
||||
let(:product2) { create(:simple_product, primary_taxon: taxon1, taxons: [taxon1, taxon2]) }
|
||||
let(:product3) { create(:simple_product, primary_taxon: taxon3) }
|
||||
let(:oc) { create(:order_cycle, distributors: [distributor]) }
|
||||
let(:ex) { create(:exchange, order_cycle: oc, incoming: false, sender: supplier, receiver: distributor) }
|
||||
|
||||
it "gets all taxons of all distributed products" do
|
||||
allow(Spree::Product).to receive(:in_distributor).and_return [product1, product2]
|
||||
expect(distributor.distributed_taxons).to match_array [taxon1, taxon2]
|
||||
end
|
||||
|
||||
it "gets all taxons of all distributed products in open order cycles" do
|
||||
Spree::Product.stub(:in_distributor).and_return [product1, product2, product3]
|
||||
ex.variants << product1.variants.first
|
||||
ex.variants << product3.variants.first
|
||||
|
||||
distributor.current_distributed_taxons.should match_array [taxon1, taxon3]
|
||||
end
|
||||
|
||||
it "gets all taxons of all supplied products" do
|
||||
allow(Spree::Product).to receive(:in_supplier).and_return [product1, product2]
|
||||
expect(supplier.supplied_taxons).to match_array [taxon1, taxon2]
|
||||
|
||||
25
spec/serializers/api/group_list_serializer_spec.rb
Normal file
25
spec/serializers/api/group_list_serializer_spec.rb
Normal file
@@ -0,0 +1,25 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Api::GroupListSerializer do
|
||||
let!(:group) { create(:enterprise_group) }
|
||||
let!(:producer) { create(:supplier_enterprise) }
|
||||
|
||||
let(:serializer) { Api::GroupListSerializer.new group }
|
||||
|
||||
before do
|
||||
group.enterprises << producer
|
||||
end
|
||||
|
||||
it "serializes group attributes" do
|
||||
expect(serializer.serializable_hash[:name]).to match group.name
|
||||
end
|
||||
|
||||
it "serializes abbreviated state" do
|
||||
expect(serializer.serializable_hash[:state]).to eq group.address.state.abbr
|
||||
end
|
||||
|
||||
it "serialises an array of enterprises" do
|
||||
expect(serializer.serializable_hash[:enterprises]).to be_a ActiveModel::ArraySerializer
|
||||
expect(serializer.serializable_hash[:enterprises].to_json).to match producer.name
|
||||
end
|
||||
end
|
||||
@@ -10,8 +10,7 @@ describe Api::EnterpriseSerializer do
|
||||
all_distributed_taxons: { enterprise.id => [123] },
|
||||
current_distributed_taxons: { enterprise.id => [123] },
|
||||
supplied_taxons: { enterprise.id => [456] },
|
||||
shipping_method_services: {},
|
||||
relatives: { enterprise.id => { producers: [123], distributors: [456] } })
|
||||
shipping_method_services: {})
|
||||
}
|
||||
|
||||
it "serializes an enterprise" do
|
||||
@@ -23,11 +22,6 @@ describe Api::EnterpriseSerializer do
|
||||
expect(serializer.serializable_hash[:supplied_taxons]).to eq([{ id: 456 }])
|
||||
end
|
||||
|
||||
it "serializes producers and hubs as ids only" do
|
||||
expect(serializer.serializable_hash[:producers]).to eq([{ id: 123 }])
|
||||
expect(serializer.serializable_hash[:hubs]).to eq([{ id: 456 }])
|
||||
end
|
||||
|
||||
it "serializes icons" do
|
||||
expect(serializer.to_json).to match "map_005-hub.svg"
|
||||
end
|
||||
|
||||
@@ -63,6 +63,12 @@ module AuthenticationWorkflow
|
||||
fill_in "password", with: user.password
|
||||
click_button "Login"
|
||||
end
|
||||
|
||||
def use_api_as_unauthenticated_user
|
||||
allow_any_instance_of(Api::BaseController).to receive(:spree_current_user) {
|
||||
Spree::User.anonymous!
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.configure do |config|
|
||||
|
||||
Reference in New Issue
Block a user