Staggered loading of products in BPE

This commit is contained in:
Rob H
2014-08-01 13:36:29 +10:00
parent b9f49344b4
commit 27e992ebcb
4 changed files with 49 additions and 50 deletions

View File

@@ -52,14 +52,23 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", [
else else
api_error_msg = "You don't have an API key yet. An attempt was made to generate one, but you are currently not authorised, please contact your site administrator for access." api_error_msg = "You don't have an API key yet. An attempt was made to generate one, but you are currently not authorised, please contact your site administrator for access."
$scope.$watch 'query', ->
$scope.limit = 15 # Reset limit whenever searching
$scope.fetchProducts = -> # WARNING: returns a promise $scope.fetchProducts = -> # WARNING: returns a promise
$scope.loading = true $scope.loading = true
queryString = $scope.currentFilters.reduce (qs,f) -> queryString = $scope.currentFilters.reduce (qs,f) ->
return qs + "q[#{f.property.db_column}_#{f.predicate.predicate}]=#{f.value};" return qs + "q[#{f.property.db_column}_#{f.predicate.predicate}]=#{f.value};"
, "" , ""
return dataFetcher("/api/products/bulk_products?page=1;per_page=500;#{queryString}").then (data) -> return dataFetcher("/api/products/bulk_products?page=1;per_page=20;#{queryString}").then (data) ->
$scope.resetProducts data $scope.resetProducts data.products
$scope.loading = false $scope.loading = false
if data.pages > 1
for page in [2..data.pages]
dataFetcher("/api/products/bulk_products?page=#{page};per_page=20;#{queryString}").then (data) ->
for product in data.products
$scope.unpackProduct product
$scope.products.push product
$scope.resetProducts = (data) -> $scope.resetProducts = (data) ->
@@ -276,7 +285,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", [
filters: $scope.currentFilters filters: $scope.currentFilters
).success((data) -> ).success((data) ->
DirtyProducts.clear() DirtyProducts.clear()
$scope.updateVariantLists(data) $scope.updateVariantLists(data.products)
$timeout -> $scope.displaySuccess() $timeout -> $scope.displaySuccess()
).error (data, status) -> ).error (data, status) ->
$scope.displayFailure "Server returned with error status: " + status $scope.displayFailure "Server returned with error status: " + status

View File

@@ -9,7 +9,7 @@ Spree::Api::ProductsController.class_eval do
def bulk_products def bulk_products
@products = product_scope.ransack(params[:q]).result.managed_by(current_api_user).page(params[:page]).per(params[:per_page]) @products = product_scope.ransack(params[:q]).result.managed_by(current_api_user).page(params[:page]).per(params[:per_page])
render text: ActiveModel::ArraySerializer.new(@products, each_serializer: Spree::Api::ProductSerializer).to_json render text: { products: ActiveModel::ArraySerializer.new(@products, each_serializer: Spree::Api::ProductSerializer), pages: @products.num_pages }.to_json
end end
def soft_delete def soft_delete

View File

@@ -51,10 +51,10 @@
%h4 Loading Products... %h4 Loading Products...
%div.sixteen.columns.alpha{ 'ng-show' => '!loading && products.length == 0' } %div.sixteen.columns.alpha{ 'ng-show' => '!loading && products.length == 0' }
%h4{ :style => 'color:red;' } No matching products found. %h4{ :style => 'color:red;' } No matching products found.
%div.sixteen.columns.alpha{ 'ng-show' => '!loading && products.length == 500' } %div.sixteen.columns.alpha{ 'ng-show' => '!loading && products.length >= 500' }
%h6 Search returned too many products to display (500+), please apply more search filters to reduce the number of matching products %h6 Search returned too many products to display (500+), please apply more search filters to reduce the number of matching products
%div.sixteen.columns.alpha{ 'ng-hide' => 'loading || products.length == 500 || products.length == 0' } %div.sixteen.columns.alpha{ 'ng-hide' => 'loading || products.length >= 500 || products.length == 0' }
%div.quick_search{ :class => "five columns omega" } %div.quick_search{ :class => "five columns alpha" }
%input.search{ :class => "four columns alpha", 'ng-model' => 'query', :name => "quick_filter", :type => 'text', 'placeholder' => 'Quick Search' } %input.search{ :class => "four columns alpha", 'ng-model' => 'query', :name => "quick_filter", :type => 'text', 'placeholder' => 'Quick Search' }
%div{ :class => "eight columns" }   %div{ :class => "eight columns" }  
%div{ :class => "three columns omega" } %div{ :class => "three columns omega" }

View File

@@ -184,8 +184,7 @@ describe "filtering products for submission to database", ->
created_at: null created_at: null
updated_at: null updated_at: null
count_on_hand: 0 count_on_hand: 0
supplier_id: 5 producer:
supplier:
id: 5 id: 5
name: "Supplier 1" name: "Supplier 1"
@@ -213,7 +212,7 @@ describe "filtering products for submission to database", ->
expect(filterSubmitProducts([testProduct])).toEqual [ expect(filterSubmitProducts([testProduct])).toEqual [
id: 1 id: 1
name: "TestProduct" name: "TestProduct"
supplier_id: 5 producer: 5
variant_unit: 'volume' variant_unit: 'volume'
variant_unit_scale: 1 variant_unit_scale: 1
variant_unit_name: 'loaf' variant_unit_name: 'loaf'
@@ -249,38 +248,45 @@ describe "AdminProductEditCtrl", ->
) )
describe "loading data upon initialisation", -> describe "loading data upon initialisation", ->
it "gets a list of suppliers and then resets products with a list of data", -> it "gets a list of producers and then resets products with a list of data", ->
$httpBackend.expectGET("/api/users/authorise_api?token=api_key").respond success: "Use of API Authorised" $httpBackend.expectGET("/api/users/authorise_api?token=api_key").respond success: "Use of API Authorised"
$httpBackend.expectGET("/api/enterprises/managed?template=bulk_index&q[is_primary_producer_eq]=true").respond "list of suppliers" $httpBackend.expectGET("/api/enterprises/managed?template=bulk_index&q[is_primary_producer_eq]=true").respond "list of producers"
spyOn($scope, "fetchProducts").andReturn "nothing" spyOn($scope, "fetchProducts").andReturn "nothing"
$scope.initialise "api_key" $scope.initialise "api_key"
$httpBackend.flush() $httpBackend.flush()
expect($scope.suppliers).toEqual "list of suppliers" expect($scope.producers).toEqual "list of producers"
expect($scope.fetchProducts.calls.length).toEqual 1 expect($scope.fetchProducts.calls.length).toEqual 1
expect($scope.spree_api_key_ok).toEqual true expect($scope.spree_api_key_ok).toEqual true
describe "fetching products", -> describe "fetching products", ->
it "makes a standard call to dataFetcher when no filters exist", -> it "makes a standard call to dataFetcher when no filters exist", ->
$httpBackend.expectGET("/api/products/managed?template=bulk_index;page=1;per_page=500;").respond "list of products" $httpBackend.expectGET("/api/products/bulk_products?page=1;per_page=20;").respond "list of products"
$scope.fetchProducts() $scope.fetchProducts()
it "calls resetProducts after data has been received", -> it "calls resetProducts after data has been received", ->
spyOn $scope, "resetProducts" spyOn $scope, "resetProducts"
$httpBackend.expectGET("/api/products/managed?template=bulk_index;page=1;per_page=500;").respond "list of products" $httpBackend.expectGET("/api/products/bulk_products?page=1;per_page=20;").respond { products: "list of products" }
$scope.fetchProducts() $scope.fetchProducts()
$httpBackend.flush() $httpBackend.flush()
expect($scope.resetProducts).toHaveBeenCalledWith "list of products" expect($scope.resetProducts).toHaveBeenCalledWith "list of products"
it "calls makes more calls to dataFetcher if more pages exist", ->
$httpBackend.expectGET("/api/products/bulk_products?page=1;per_page=20;").respond { products: [], pages: 2 }
$httpBackend.expectGET("/api/products/bulk_products?page=2;per_page=20;").respond { products: ["list of products"] }
$scope.fetchProducts()
$httpBackend.flush()
it "applies filters when they are present", -> it "applies filters when they are present", ->
filter = {property: $scope.filterableColumns[1], predicate:$scope.filterTypes[0], value:"Product1"} filter = {property: $scope.filterableColumns[1], predicate:$scope.filterTypes[0], value:"Product1"}
$scope.currentFilters.push filter # Don't use addFilter as that is not what we are testing $scope.currentFilters.push filter # Don't use addFilter as that is not what we are testing
expect($scope.currentFilters).toEqual [filter] expect($scope.currentFilters).toEqual [filter]
$httpBackend.expectGET("/api/products/managed?template=bulk_index;page=1;per_page=500;q[name_eq]=Product1;").respond "list of products" $httpBackend.expectGET("/api/products/bulk_products?page=1;per_page=20;q[name_eq]=Product1;").respond "list of products"
$scope.fetchProducts() $scope.fetchProducts()
$httpBackend.flush()
it "sets the loading property to true before fetching products and unsets it when loading is complete", -> it "sets the loading property to true before fetching products and unsets it when loading is complete", ->
$httpBackend.expectGET("/api/products/managed?template=bulk_index;page=1;per_page=500;").respond "list of products" $httpBackend.expectGET("/api/products/bulk_products?page=1;per_page=20;").respond "list of products"
$scope.fetchProducts() $scope.fetchProducts()
expect($scope.loading).toEqual true expect($scope.loading).toEqual true
$httpBackend.flush() $httpBackend.flush()
@@ -324,7 +330,7 @@ describe "AdminProductEditCtrl", ->
describe "preparing products", -> describe "preparing products", ->
beforeEach -> beforeEach ->
spyOn $scope, "matchSupplier" spyOn $scope, "matchProducer"
spyOn $scope, "loadVariantUnit" spyOn $scope, "loadVariantUnit"
it "initialises display properties for the product", -> it "initialises display properties for the product", ->
@@ -333,11 +339,11 @@ describe "AdminProductEditCtrl", ->
$scope.unpackProduct product $scope.unpackProduct product
expect($scope.displayProperties[123]).toEqual {showVariants: false} expect($scope.displayProperties[123]).toEqual {showVariants: false}
it "calls matchSupplier for the product", -> it "calls matchProducer for the product", ->
product = {id: 123} product = {id: 123}
$scope.displayProperties = {} $scope.displayProperties = {}
$scope.unpackProduct product $scope.unpackProduct product
expect($scope.matchSupplier.calls.length).toEqual 1 expect($scope.matchProducer.calls.length).toEqual 1
it "calls loadVariantUnit for the product", -> it "calls loadVariantUnit for the product", ->
product = {id: 123} product = {id: 123}
@@ -346,31 +352,19 @@ describe "AdminProductEditCtrl", ->
expect($scope.loadVariantUnit.calls.length).toEqual 1 expect($scope.loadVariantUnit.calls.length).toEqual 1
describe "matching supplier", -> describe "matching producer", ->
it "changes the supplier of the product to the one which matches it from the suppliers list", -> it "changes the producer of the product to the one which matches it from the producers list", ->
s1_s = $scope.producers = [
id: 1 { id: 1, name: "S1" }
name: "S1" { id: 2, name: "S2" }
s2_s =
id: 2
name: "S2"
s1_p =
id: 1
name: "S1"
expect(s1_s is s1_p).not.toEqual true
$scope.suppliers = [
s1_s
s2_s
] ]
product = product =
id: 10 id: 10
supplier: s1_p producer: 1
$scope.matchSupplier product $scope.matchProducer product
expect(product.supplier is s1_s).toEqual true expect(product.producer).toBe $scope.producers[0]
describe "loading variant unit", -> describe "loading variant unit", ->
@@ -1059,7 +1053,7 @@ describe "AdminProductEditCtrl", ->
$scope.cloneProduct $scope.products[0] $scope.cloneProduct $scope.products[0]
$httpBackend.flush() $httpBackend.flush()
it "adds the newly created product to $scope.products and matches supplier", -> it "adds the newly created product to $scope.products and matches producer", ->
spyOn($scope, "unpackProduct").andCallThrough() spyOn($scope, "unpackProduct").andCallThrough()
$scope.products = [ $scope.products = [
id: 13 id: 13
@@ -1069,8 +1063,7 @@ describe "AdminProductEditCtrl", ->
product: product:
id: 17 id: 17
name: "new_product" name: "new_product"
supplier: producer: 6
id: 6
variants: [ variants: [
id: 3 id: 3
@@ -1080,8 +1073,7 @@ describe "AdminProductEditCtrl", ->
$httpBackend.expectGET("/api/products/17?template=bulk_show").respond 200, $httpBackend.expectGET("/api/products/17?template=bulk_show").respond 200,
id: 17 id: 17
name: "new_product" name: "new_product"
supplier: producer: 6
id: 6
variants: [ variants: [
id: 3 id: 3
@@ -1094,8 +1086,7 @@ describe "AdminProductEditCtrl", ->
id: 17 id: 17
name: "new_product" name: "new_product"
variant_unit_with_scale: null variant_unit_with_scale: null
supplier: producer: 6
id: 6
variants: [ variants: [
id: 3 id: 3
@@ -1112,8 +1103,7 @@ describe "AdminProductEditCtrl", ->
id: 17 id: 17
name: "new_product" name: "new_product"
variant_unit_with_scale: null variant_unit_with_scale: null
supplier: producer: 6
id: 6
variants: [ variants: [
id: 3 id: 3