From d5e42ee1e56b1d9f0fbc945ea059ab50aba6bdc6 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Mon, 18 Nov 2019 14:51:34 +0000 Subject: [PATCH 01/16] Paginate exchange products results This commit breaks the OC page when there are more than 100 products in an exchange --- .../services/exchange_product.js.coffee | 2 +- .../api/exchange_products_controller.rb | 40 ++++++++++++++----- .../api/exchange_products_controller_spec.rb | 6 +-- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee b/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee index dfc8adeca5..056db9ee46 100644 --- a/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee @@ -11,5 +11,5 @@ angular.module('admin.orderCycles').factory('ExchangeProduct', ($resource) -> index: (params={}, callback=null) -> ExchangeProductResource.index params, (data) => @loaded = true - (callback || angular.noop)(data) + (callback || angular.noop)(data.products) }) diff --git a/app/controllers/api/exchange_products_controller.rb b/app/controllers/api/exchange_products_controller.rb index c87fb95c26..01070a6c9a 100644 --- a/app/controllers/api/exchange_products_controller.rb +++ b/app/controllers/api/exchange_products_controller.rb @@ -1,6 +1,9 @@ # This controller lists products that can be added to an exchange module Api class ExchangeProductsController < Api::BaseController + DEFAULT_PAGE = 1 + DEFAULT_PER_PAGE = 100 + skip_authorization_check only: [:index] # If exchange_id is present in the URL: @@ -17,20 +20,17 @@ module Api load_data_from_other_params end - render_products + render_paginated_products products end private - def render_products - products = ExchangeProductsRenderer. + def products + ExchangeProductsRenderer. new(@order_cycle, spree_current_user). - exchange_products(@incoming, @enterprise) - - render json: products, - each_serializer: Api::Admin::ForOrderCycle::SuppliedProductSerializer, - order_cycle: @order_cycle, - status: :ok + exchange_products(@incoming, @enterprise). + page(params[:page] || DEFAULT_PAGE). + per(params[:per_page] || DEFAULT_PER_PAGE) end def load_data_from_exchange @@ -51,5 +51,27 @@ module Api end @incoming = params[:incoming] end + + def render_paginated_products(products) + serializer = ActiveModel::ArraySerializer.new( + products, + each_serializer: Api::Admin::ForOrderCycle::SuppliedProductSerializer, + order_cycle: @order_cycle + ) + + render text: { + products: serializer, + pagination: pagination_data(products) + }.to_json + end + + def pagination_data(results) + { + results: results.total_count, + pages: results.num_pages, + page: (params[:page] || DEFAULT_PAGE).to_i, + per_page: (params[:per_page] || DEFAULT_PER_PAGE).to_i + } + end end end diff --git a/spec/controllers/api/exchange_products_controller_spec.rb b/spec/controllers/api/exchange_products_controller_spec.rb index 93fcf670f4..86aa27dd73 100644 --- a/spec/controllers/api/exchange_products_controller_spec.rb +++ b/spec/controllers/api/exchange_products_controller_spec.rb @@ -17,7 +17,7 @@ module Api exchange = order_cycle.exchanges.incoming.first spree_get :index, exchange_id: exchange.id - expect(json_response.first["supplier_name"]).to eq exchange.variants.first.product.supplier.name + expect(json_response["products"].first["supplier_name"]).to eq exchange.variants.first.product.supplier.name end end @@ -27,8 +27,8 @@ module Api spree_get :index, exchange_id: exchange.id suppliers = [exchange.variants[0].product.supplier.name, exchange.variants[1].product.supplier.name] - expect(suppliers).to include json_response.first["supplier_name"] - expect(suppliers).to include json_response.second["supplier_name"] + expect(suppliers).to include json_response["products"].first["supplier_name"] + expect(suppliers).to include json_response["products"].second["supplier_name"] end end end From 00478cc57c8406f4e77eeac5678557e1930548d6 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Tue, 19 Nov 2019 11:04:05 +0000 Subject: [PATCH 02/16] Add count variants endpoint and use it instead of loading exchange products --- .../controllers/incoming_controller.js.coffee | 19 ++++-------- .../services/exchange_product.js.coffee | 9 ++++-- .../api/exchange_products_controller.rb | 31 ++++++++++++++----- .../incoming_controller_spec.js.coffee | 15 --------- 4 files changed, 35 insertions(+), 39 deletions(-) diff --git a/app/assets/javascripts/admin/order_cycles/controllers/incoming_controller.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/incoming_controller.js.coffee index 5e34e42c72..3f8539d455 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/incoming_controller.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/incoming_controller.js.coffee @@ -1,4 +1,4 @@ -angular.module('admin.orderCycles').controller 'AdminOrderCycleIncomingCtrl', ($scope, $controller, $location, Enterprise, OrderCycle, ocInstance) -> +angular.module('admin.orderCycles').controller 'AdminOrderCycleIncomingCtrl', ($scope, $controller, $location, Enterprise, OrderCycle, ExchangeProduct, ocInstance) -> $controller('AdminOrderCycleExchangesCtrl', {$scope: $scope, ocInstance: ocInstance, $location: $location}) $scope.view = 'incoming' @@ -9,18 +9,11 @@ angular.module('admin.orderCycles').controller 'AdminOrderCycleIncomingCtrl', ($ enterprise = $scope.enterprises[exchange.enterprise_id] return enterprise.numVariants if enterprise.numVariants? - $scope.loadExchangeProducts(exchange) - return unless enterprise.supplied_products? - - enterprise.numVariants = $scope.countVariants(enterprise.supplied_products) - - $scope.countVariants = (products) -> - return 0 unless products - - numVariants = 0 - for product in products - numVariants += product.variants.length - numVariants + enterprise.numVariants = 0 + params = { exchange_id: exchange.id, enterprise_id: exchange.enterprise_id, order_cycle_id: $scope.order_cycle.id, incoming: true} + ExchangeProduct.countVariants params, (variants_count) -> + enterprise.numVariants = variants_count + return enterprise.numVariants $scope.addSupplier = ($event) -> $event.preventDefault() diff --git a/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee b/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee index 056db9ee46..7f9b3989fe 100644 --- a/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee @@ -1,8 +1,7 @@ angular.module('admin.orderCycles').factory('ExchangeProduct', ($resource) -> ExchangeProductResource = $resource('/api/exchanges/:exchange_id/products.json', {}, { - 'index': - method: 'GET' - isArray: true + 'index': { method: 'GET' } + 'variant_count': { method: 'GET', params: { action_name: "variant_count" }} }) { ExchangeProductResource: ExchangeProductResource @@ -12,4 +11,8 @@ angular.module('admin.orderCycles').factory('ExchangeProduct', ($resource) -> ExchangeProductResource.index params, (data) => @loaded = true (callback || angular.noop)(data.products) + + countVariants: (params={}, callback=null) -> + ExchangeProductResource.variant_count params, (data) => + (callback || angular.noop)(data.count) }) diff --git a/app/controllers/api/exchange_products_controller.rb b/app/controllers/api/exchange_products_controller.rb index 01070a6c9a..e9e3ec537b 100644 --- a/app/controllers/api/exchange_products_controller.rb +++ b/app/controllers/api/exchange_products_controller.rb @@ -20,15 +20,30 @@ module Api load_data_from_other_params end - render_paginated_products products + render_variant_count && return if params[:action_name] == "variant_count" + + render_paginated_products paginated_products end private + def render_variant_count + render text: { + count: Spree::Variant. + not_master. + where(product_id: products). + count + }.to_json + end + def products ExchangeProductsRenderer. new(@order_cycle, spree_current_user). - exchange_products(@incoming, @enterprise). + exchange_products(@incoming, @enterprise) + end + + def paginated_products + products. page(params[:page] || DEFAULT_PAGE). per(params[:per_page] || DEFAULT_PER_PAGE) end @@ -52,23 +67,23 @@ module Api @incoming = params[:incoming] end - def render_paginated_products(products) + def render_paginated_products(paginated_products) serializer = ActiveModel::ArraySerializer.new( - products, + paginated_products, each_serializer: Api::Admin::ForOrderCycle::SuppliedProductSerializer, order_cycle: @order_cycle ) render text: { products: serializer, - pagination: pagination_data(products) + pagination: pagination_data(paginated_products) }.to_json end - def pagination_data(results) + def pagination_data(paginated_products) { - results: results.total_count, - pages: results.num_pages, + results: paginated_products.total_count, + pages: paginated_products.num_pages, page: (params[:page] || DEFAULT_PAGE).to_i, per_page: (params[:per_page] || DEFAULT_PER_PAGE).to_i } diff --git a/spec/javascripts/unit/admin/order_cycles/controllers/incoming_controller_spec.js.coffee b/spec/javascripts/unit/admin/order_cycles/controllers/incoming_controller_spec.js.coffee index e650317e44..73deb77adc 100644 --- a/spec/javascripts/unit/admin/order_cycles/controllers/incoming_controller_spec.js.coffee +++ b/spec/javascripts/unit/admin/order_cycles/controllers/incoming_controller_spec.js.coffee @@ -23,21 +23,6 @@ describe 'AdminOrderCycleIncomingCtrl', -> inject ($controller) -> ctrl = $controller 'AdminOrderCycleIncomingCtrl', {$scope: scope, $location: location, OrderCycle: OrderCycle, Enterprise: Enterprise, EnterpriseFee: EnterpriseFee, ocInstance: ocInstance} - it 'counts total variants in a list of products', -> - products = [ - {variants: [{}]}, - {variants: [{}]}, - {variants: [{}, {}, {}]} - ] - - expect(scope.countVariants(products)).toEqual(5) - - it 'returns zero when products list is null', -> - expect(scope.countVariants(null)).toEqual(0) - - it 'returns zero when products list is empty', -> - expect(scope.countVariants([])).toEqual(0) - it 'adds order cycle suppliers', -> scope.new_supplier_id = 'new supplier id' From cfe3f72d0e9c1034167210e8d04b330638494de0 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Tue, 19 Nov 2019 16:28:00 +0000 Subject: [PATCH 03/16] Add load more button to list of exchange products --- .../order_cycle_exchanges_controller.js.coffee | 16 +++++++++++----- .../exchange_distributed_products.html.haml | 3 +++ .../panels/exchange_supplied_products.html.haml | 3 +++ .../admin/order_cycles/_exchange_form.html.haml | 4 ++-- config/locales/en.yml | 2 ++ 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee index 066bcaf25c..bd233106ee 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee @@ -36,14 +36,20 @@ angular.module('admin.orderCycles') $scope.removeDistributionOfVariant = (variant_id) -> OrderCycle.removeDistributionOfVariant(variant_id) - $scope.loadExchangeProducts = (exchange) -> - return if $scope.enterprises[exchange.enterprise_id].supplied_products_fetched? - $scope.enterprises[exchange.enterprise_id].supplied_products_fetched = true + $scope.loadExchangeProducts = (exchange, page = 1) -> + enterprise = $scope.enterprises[exchange.enterprise_id] + + return if enterprise.last_page_loaded? && enterprise.last_page_loaded >= page + enterprise.last_page_loaded = page incoming = true if $scope.view == 'incoming' - params = { exchange_id: exchange.id, enterprise_id: exchange.enterprise_id, order_cycle_id: $scope.order_cycle.id, incoming: incoming} + params = { exchange_id: exchange.id, enterprise_id: exchange.enterprise_id, order_cycle_id: $scope.order_cycle.id, incoming: incoming, page: page} ExchangeProduct.index params, (products) -> - $scope.enterprises[exchange.enterprise_id].supplied_products = products + enterprise.supplied_products = [] unless enterprise.supplied_products? + enterprise.supplied_products.push products... + + $scope.loadMoreExchangeProducts = -> + $scope.loadExchangeProducts(this.exchange, this.enterprises[this.exchange.enterprise_id].last_page_loaded + 1) # initialize exchange products panel if not yet done $scope.exchangeProdutsPanelInitialized = [] diff --git a/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml index 4dad8310ce..5cfb64526c 100644 --- a/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml +++ b/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml @@ -26,3 +26,6 @@ 'id' => 'order_cycle_outgoing_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}', 'ng-disabled' => '!order_cycle.editable_variants_for_outgoing_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_outgoing_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' } {{ variant.label }} + .pagination + .button{ 'ng-click' => 'loadMoreExchangeProducts()' } + {{ 'js.admin.panels.exchange_products.load_more_products' | t }} diff --git a/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml index e6c80e973a..a1930bc9ad 100644 --- a/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml +++ b/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml @@ -27,3 +27,6 @@ 'id' => 'order_cycle_incoming_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}', 'ng-disabled' => '!order_cycle.editable_variants_for_incoming_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_incoming_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' } {{ variant.label }} + .pagination + .button{ 'ng-click' => 'loadMoreExchangeProducts()' } + {{ 'js.admin.panels.exchange_products.load_more_products' | t }} diff --git a/app/views/admin/order_cycles/_exchange_form.html.haml b/app/views/admin/order_cycles/_exchange_form.html.haml index 63a44e9a3b..19c0172165 100644 --- a/app/views/admin/order_cycles/_exchange_form.html.haml +++ b/app/views/admin/order_cycles/_exchange_form.html.haml @@ -35,10 +35,10 @@ - if type == 'supplier' %tr.panel-row{ object: "exchange", panels: "{products: 'exchange_supplied_products'}", - locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,suppliedVariants,removeDistributionOfVariant,initializeExchangeProductsPanel", + locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,suppliedVariants,removeDistributionOfVariant,initializeExchangeProductsPanel,loadMoreExchangeProducts", colspan: 4 } - if type == 'distributor' %tr.panel-row{ object: "exchange", panels: "{products: 'exchange_distributed_products', tags: 'exchange_tags'}", - locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,incomingExchangeVariantsFor,variantSuppliedToOrderCycle,initializeExchangeProductsPanel", + locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,incomingExchangeVariantsFor,variantSuppliedToOrderCycle,initializeExchangeProductsPanel,loadMoreExchangeProducts", colspan: 5 } diff --git a/config/locales/en.yml b/config/locales/en.yml index f1945520a0..7ca682af94 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2560,6 +2560,8 @@ See the %{link} to find out more about %{sitename}'s features and to start using severity: Severity description: Description resolve: Resolve + exchange_products: + load_more_products: "Load More Products" tag_rules: shipping_method_tagged_top: "Shipping methods tagged" shipping_method_tagged_bottom: "are:" From 041652177246dbd92a508e68fdf6b279ecfe5570 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Thu, 21 Nov 2019 13:14:30 +0000 Subject: [PATCH 04/16] Add load all prouducts button to list of exchange products --- .../order_cycle_exchanges_controller.js.coffee | 10 ++++++++-- .../order_cycles/services/exchange_product.js.coffee | 2 +- .../panels/exchange_distributed_products.html.haml | 2 ++ .../admin/panels/exchange_supplied_products.html.haml | 2 ++ app/views/admin/order_cycles/_exchange_form.html.haml | 4 ++-- config/locales/en.yml | 1 + 6 files changed, 16 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee index bd233106ee..1953754cbf 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee @@ -44,12 +44,18 @@ angular.module('admin.orderCycles') incoming = true if $scope.view == 'incoming' params = { exchange_id: exchange.id, enterprise_id: exchange.enterprise_id, order_cycle_id: $scope.order_cycle.id, incoming: incoming, page: page} - ExchangeProduct.index params, (products) -> + ExchangeProduct.index params, (products, last_page) -> + enterprise.last_page = last_page enterprise.supplied_products = [] unless enterprise.supplied_products? enterprise.supplied_products.push products... $scope.loadMoreExchangeProducts = -> - $scope.loadExchangeProducts(this.exchange, this.enterprises[this.exchange.enterprise_id].last_page_loaded + 1) + $scope.loadExchangeProducts(this.exchange, $scope.enterprises[this.exchange.enterprise_id].last_page_loaded + 1) + + $scope.loadAllExchangeProducts = -> + enterprise = $scope.enterprises[this.exchange.enterprise_id] + for page_to_load in [(enterprise.last_page_loaded + 1)..enterprise.last_page] + $scope.loadExchangeProducts(this.exchange, page_to_load) # initialize exchange products panel if not yet done $scope.exchangeProdutsPanelInitialized = [] diff --git a/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee b/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee index 7f9b3989fe..92df8f8e84 100644 --- a/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee @@ -10,7 +10,7 @@ angular.module('admin.orderCycles').factory('ExchangeProduct', ($resource) -> index: (params={}, callback=null) -> ExchangeProductResource.index params, (data) => @loaded = true - (callback || angular.noop)(data.products) + (callback || angular.noop)(data.products, data.pagination.pages) countVariants: (params={}, callback=null) -> ExchangeProductResource.variant_count params, (data) => diff --git a/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml index 5cfb64526c..45650d94db 100644 --- a/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml +++ b/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml @@ -29,3 +29,5 @@ .pagination .button{ 'ng-click' => 'loadMoreExchangeProducts()' } {{ 'js.admin.panels.exchange_products.load_more_products' | t }} + .button{ 'ng-click' => 'loadAllExchangeProducts()' } + {{ 'js.admin.panels.exchange_products.load_all_products' | t }} diff --git a/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml index a1930bc9ad..c2dc200772 100644 --- a/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml +++ b/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml @@ -30,3 +30,5 @@ .pagination .button{ 'ng-click' => 'loadMoreExchangeProducts()' } {{ 'js.admin.panels.exchange_products.load_more_products' | t }} + .button{ 'ng-click' => 'loadAllExchangeProducts()' } + {{ 'js.admin.panels.exchange_products.load_all_products' | t }} diff --git a/app/views/admin/order_cycles/_exchange_form.html.haml b/app/views/admin/order_cycles/_exchange_form.html.haml index 19c0172165..634262028d 100644 --- a/app/views/admin/order_cycles/_exchange_form.html.haml +++ b/app/views/admin/order_cycles/_exchange_form.html.haml @@ -35,10 +35,10 @@ - if type == 'supplier' %tr.panel-row{ object: "exchange", panels: "{products: 'exchange_supplied_products'}", - locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,suppliedVariants,removeDistributionOfVariant,initializeExchangeProductsPanel,loadMoreExchangeProducts", + locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,suppliedVariants,removeDistributionOfVariant,initializeExchangeProductsPanel,loadMoreExchangeProducts,loadAllExchangeProducts", colspan: 4 } - if type == 'distributor' %tr.panel-row{ object: "exchange", panels: "{products: 'exchange_distributed_products', tags: 'exchange_tags'}", - locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,incomingExchangeVariantsFor,variantSuppliedToOrderCycle,initializeExchangeProductsPanel,loadMoreExchangeProducts", + locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,incomingExchangeVariantsFor,variantSuppliedToOrderCycle,initializeExchangeProductsPanel,loadMoreExchangeProducts,loadAllExchangeProducts", colspan: 5 } diff --git a/config/locales/en.yml b/config/locales/en.yml index 7ca682af94..b07869f3a1 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2562,6 +2562,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using resolve: Resolve exchange_products: load_more_products: "Load More Products" + load_all_products: "Load All Products" tag_rules: shipping_method_tagged_top: "Shipping methods tagged" shipping_method_tagged_bottom: "are:" From 2f7fd1482a803a30bd3b637b22e02e111e5982a6 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Thu, 21 Nov 2019 18:16:27 +0000 Subject: [PATCH 05/16] Add link to load all products at the top of the list of products and include summary of number of products loaded already --- .../order_cycle_exchanges_controller.js.coffee | 9 +++++---- .../order_cycles/services/exchange_product.js.coffee | 2 +- .../admin/panels/exchange_distributed_products.html.haml | 8 +++++++- .../admin/panels/exchange_supplied_products.html.haml | 8 +++++++- app/assets/stylesheets/admin/openfoodnetwork.css.scss | 6 +++++- config/locales/en.yml | 2 ++ 6 files changed, 27 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee index 1953754cbf..9e966575d5 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee @@ -38,15 +38,16 @@ angular.module('admin.orderCycles') $scope.loadExchangeProducts = (exchange, page = 1) -> enterprise = $scope.enterprises[exchange.enterprise_id] + enterprise.supplied_products ?= [] return if enterprise.last_page_loaded? && enterprise.last_page_loaded >= page enterprise.last_page_loaded = page incoming = true if $scope.view == 'incoming' params = { exchange_id: exchange.id, enterprise_id: exchange.enterprise_id, order_cycle_id: $scope.order_cycle.id, incoming: incoming, page: page} - ExchangeProduct.index params, (products, last_page) -> - enterprise.last_page = last_page - enterprise.supplied_products = [] unless enterprise.supplied_products? + ExchangeProduct.index params, (products, num_of_pages, num_of_products) -> + enterprise.num_of_pages = num_of_pages + enterprise.num_of_products = num_of_products enterprise.supplied_products.push products... $scope.loadMoreExchangeProducts = -> @@ -54,7 +55,7 @@ angular.module('admin.orderCycles') $scope.loadAllExchangeProducts = -> enterprise = $scope.enterprises[this.exchange.enterprise_id] - for page_to_load in [(enterprise.last_page_loaded + 1)..enterprise.last_page] + for page_to_load in [(enterprise.last_page_loaded + 1)..enterprise.num_of_pages] $scope.loadExchangeProducts(this.exchange, page_to_load) # initialize exchange products panel if not yet done diff --git a/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee b/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee index 92df8f8e84..1a80c637d5 100644 --- a/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee @@ -10,7 +10,7 @@ angular.module('admin.orderCycles').factory('ExchangeProduct', ($resource) -> index: (params={}, callback=null) -> ExchangeProductResource.index params, (data) => @loaded = true - (callback || angular.noop)(data.products, data.pagination.pages) + (callback || angular.noop)(data.products, data.pagination.pages, data.pagination.results) countVariants: (params={}, callback=null) -> ExchangeProductResource.variant_count params, (data) => diff --git a/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml index 45650d94db..d92e5e1fe5 100644 --- a/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml +++ b/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml @@ -1,5 +1,11 @@ .row.exchange-distributed-products{'ng-init' => 'initializeExchangeProductsPanel(exchange)'} .sixteen.columns.alpha.omega + .exchange-load-all-variants + %div + {{ 'js.admin.panels.exchange_products.products_loaded' | t:{ num_of_products_loaded: enterprises[exchange.enterprise_id].supplied_products.length, total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }} + %a{ 'ng-click' => 'loadAllExchangeProducts()' } + {{ 'js.admin.panels.exchange_products.load_all_products' | t }} + .exchange-select-all-variants %label %input{ type: 'checkbox', name: 'order_cycle_outgoing_exchange_{{ $parent.$index }}_select_all_variants', @@ -7,7 +13,7 @@ 'ng-model' => 'exchange.select_all_variants', 'ng-change' => 'setExchangeVariants(exchange, incomingExchangeVariantsFor(exchange.enterprise_id), exchange.select_all_variants)', 'id' => 'order_cycle_outgoing_exchange_{{ $parent.$index }}_select_all_variants' } - {{ 'admin.select_all' | t }} + {{ 'js.admin.panels.exchange_products.select_all_products' | t:{ total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }} .exchange-products -# Scope product list based on permissions the current user has to view variants in this exchange diff --git a/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml index c2dc200772..cac2c373ce 100644 --- a/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml +++ b/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml @@ -1,5 +1,11 @@ .row.exchange-supplied-products{'ng-init' => 'initializeExchangeProductsPanel(exchange)'} .sixteen.columns.alpha.omega + .exchange-load-all-variants + %div + {{ 'js.admin.panels.exchange_products.products_loaded' | t:{ num_of_products_loaded: enterprises[exchange.enterprise_id].supplied_products.length, total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }} + %a{ 'ng-click' => 'loadAllExchangeProducts()' } + {{ 'js.admin.panels.exchange_products.load_all_products' | t }} + .exchange-select-all-variants %label %input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants', @@ -7,7 +13,7 @@ 'ng-model' => 'exchange.select_all_variants', 'ng-change' => 'setExchangeVariants(exchange, suppliedVariants(exchange.enterprise_id), exchange.select_all_variants)', 'id' => 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants' } - {{ 'admin.select_all' | t }} + {{ 'js.admin.panels.exchange_products.select_all_products' | t:{ total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }} .exchange-products -# No need to scope product list based on permissions, because if an incoming exchange is visible, diff --git a/app/assets/stylesheets/admin/openfoodnetwork.css.scss b/app/assets/stylesheets/admin/openfoodnetwork.css.scss index 8cdc6c3e87..f26fbc992f 100644 --- a/app/assets/stylesheets/admin/openfoodnetwork.css.scss +++ b/app/assets/stylesheets/admin/openfoodnetwork.css.scss @@ -104,9 +104,13 @@ form.order_cycle { width: 20px; } + .exchange-load-all-variants { + margin: 0px 5px 20px 5px; + } + .exchange-select-all-variants { clear: both; - margin: 5px; + margin: 15px 5px 25px 5px; } .exchange-products { diff --git a/config/locales/en.yml b/config/locales/en.yml index b07869f3a1..8bb7d33cd1 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2563,6 +2563,8 @@ See the %{link} to find out more about %{sitename}'s features and to start using exchange_products: load_more_products: "Load More Products" load_all_products: "Load All Products" + select_all_products: "Select All %{total_number_of_products} Products" + products_loaded: "%{num_of_products_loaded} of %{total_number_of_products} Products Loaded" tag_rules: shipping_method_tagged_top: "Shipping methods tagged" shipping_method_tagged_bottom: "are:" From 1a9c3007b009893fbd50202db84158e79eb50821 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Thu, 21 Nov 2019 20:00:53 +0000 Subject: [PATCH 06/16] Make select all work again in incoming exchanges by loading alll products before triggering the select all process --- .../controllers/incoming_controller.js.coffee | 9 +++++++++ .../order_cycle_exchanges_controller.js.coffee | 13 ++++++++----- .../panels/exchange_distributed_products.html.haml | 6 +++--- .../panels/exchange_supplied_products.html.haml | 8 ++++---- .../admin/order_cycles/_exchange_form.html.haml | 2 +- 5 files changed, 25 insertions(+), 13 deletions(-) diff --git a/app/assets/javascripts/admin/order_cycles/controllers/incoming_controller.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/incoming_controller.js.coffee index 3f8539d455..ef72e3f0e5 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/incoming_controller.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/incoming_controller.js.coffee @@ -18,3 +18,12 @@ angular.module('admin.orderCycles').controller 'AdminOrderCycleIncomingCtrl', ($ $scope.addSupplier = ($event) -> $event.preventDefault() OrderCycle.addSupplier $scope.new_supplier_id + + # To select all variants we first need to load them all from the server + # + # This is only needed in Incoming exchanges as here we use supplied_products, + # in Outgoing Exchanges the variants are loaded as part of the Exchange payload + $scope.selectAllVariants = (exchange, selected) -> + Promise.all($scope.loadAllExchangeProducts(exchange)).then -> + $scope.setExchangeVariants(exchange, $scope.suppliedVariants(exchange.enterprise_id), selected) + $scope.$apply() diff --git a/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee index 9e966575d5..eb38dee815 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee @@ -50,13 +50,16 @@ angular.module('admin.orderCycles') enterprise.num_of_products = num_of_products enterprise.supplied_products.push products... - $scope.loadMoreExchangeProducts = -> - $scope.loadExchangeProducts(this.exchange, $scope.enterprises[this.exchange.enterprise_id].last_page_loaded + 1) + $scope.loadMoreExchangeProducts = (exchange) -> + $scope.loadExchangeProducts(exchange, $scope.enterprises[exchange.enterprise_id].last_page_loaded + 1) - $scope.loadAllExchangeProducts = -> - enterprise = $scope.enterprises[this.exchange.enterprise_id] + $scope.loadAllExchangeProducts = (exchange) -> + enterprise = $scope.enterprises[exchange.enterprise_id] + return [] if enterprise.last_page_loaded >= enterprise.num_of_pages + all_promises = [] for page_to_load in [(enterprise.last_page_loaded + 1)..enterprise.num_of_pages] - $scope.loadExchangeProducts(this.exchange, page_to_load) + all_promises.push $scope.loadExchangeProducts(exchange, page_to_load).$promise + all_promises # initialize exchange products panel if not yet done $scope.exchangeProdutsPanelInitialized = [] diff --git a/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml index d92e5e1fe5..32f6f37d52 100644 --- a/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml +++ b/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml @@ -3,7 +3,7 @@ .exchange-load-all-variants %div {{ 'js.admin.panels.exchange_products.products_loaded' | t:{ num_of_products_loaded: enterprises[exchange.enterprise_id].supplied_products.length, total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }} - %a{ 'ng-click' => 'loadAllExchangeProducts()' } + %a{ 'ng-click' => 'loadAllExchangeProducts(exchange)' } {{ 'js.admin.panels.exchange_products.load_all_products' | t }} .exchange-select-all-variants @@ -33,7 +33,7 @@ 'ng-disabled' => '!order_cycle.editable_variants_for_outgoing_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_outgoing_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' } {{ variant.label }} .pagination - .button{ 'ng-click' => 'loadMoreExchangeProducts()' } + .button{ 'ng-click' => 'loadMoreExchangeProducts(exchange)' } {{ 'js.admin.panels.exchange_products.load_more_products' | t }} - .button{ 'ng-click' => 'loadAllExchangeProducts()' } + .button{ 'ng-click' => 'loadAllExchangeProducts(exchange)' } {{ 'js.admin.panels.exchange_products.load_all_products' | t }} diff --git a/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml index cac2c373ce..3217c1f722 100644 --- a/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml +++ b/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml @@ -3,7 +3,7 @@ .exchange-load-all-variants %div {{ 'js.admin.panels.exchange_products.products_loaded' | t:{ num_of_products_loaded: enterprises[exchange.enterprise_id].supplied_products.length, total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }} - %a{ 'ng-click' => 'loadAllExchangeProducts()' } + %a{ 'ng-click' => 'loadAllExchangeProducts(exchange)' } {{ 'js.admin.panels.exchange_products.load_all_products' | t }} .exchange-select-all-variants @@ -11,7 +11,7 @@ %input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants', value: 1, 'ng-model' => 'exchange.select_all_variants', - 'ng-change' => 'setExchangeVariants(exchange, suppliedVariants(exchange.enterprise_id), exchange.select_all_variants)', + 'ng-change' => 'selectAllVariants(exchange, exchange.select_all_variants)', 'id' => 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants' } {{ 'js.admin.panels.exchange_products.select_all_products' | t:{ total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }} @@ -34,7 +34,7 @@ 'ng-disabled' => '!order_cycle.editable_variants_for_incoming_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_incoming_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' } {{ variant.label }} .pagination - .button{ 'ng-click' => 'loadMoreExchangeProducts()' } + .button{ 'ng-click' => 'loadMoreExchangeProducts(exchange)' } {{ 'js.admin.panels.exchange_products.load_more_products' | t }} - .button{ 'ng-click' => 'loadAllExchangeProducts()' } + .button{ 'ng-click' => 'loadAllExchangeProducts(exchange)' } {{ 'js.admin.panels.exchange_products.load_all_products' | t }} diff --git a/app/views/admin/order_cycles/_exchange_form.html.haml b/app/views/admin/order_cycles/_exchange_form.html.haml index 634262028d..b89016c22b 100644 --- a/app/views/admin/order_cycles/_exchange_form.html.haml +++ b/app/views/admin/order_cycles/_exchange_form.html.haml @@ -35,7 +35,7 @@ - if type == 'supplier' %tr.panel-row{ object: "exchange", panels: "{products: 'exchange_supplied_products'}", - locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,suppliedVariants,removeDistributionOfVariant,initializeExchangeProductsPanel,loadMoreExchangeProducts,loadAllExchangeProducts", + locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,selectAllVariants,suppliedVariants,removeDistributionOfVariant,initializeExchangeProductsPanel,loadMoreExchangeProducts,loadAllExchangeProducts", colspan: 4 } - if type == 'distributor' %tr.panel-row{ object: "exchange", From 3e5b7ebbf1a041465779f75fdde716101466e874 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Sun, 24 Nov 2019 13:35:03 +0000 Subject: [PATCH 07/16] Show exchange products list only after first page of products is loaded --- .../admin/panels/exchange_distributed_products.html.haml | 2 +- .../templates/admin/panels/exchange_supplied_products.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml index 32f6f37d52..34feaff957 100644 --- a/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml +++ b/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml @@ -1,5 +1,5 @@ .row.exchange-distributed-products{'ng-init' => 'initializeExchangeProductsPanel(exchange)'} - .sixteen.columns.alpha.omega + .sixteen.columns.alpha.omega{ 'ng-show' => 'enterprises[exchange.enterprise_id].supplied_products.length != 0' } .exchange-load-all-variants %div {{ 'js.admin.panels.exchange_products.products_loaded' | t:{ num_of_products_loaded: enterprises[exchange.enterprise_id].supplied_products.length, total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }} diff --git a/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml index 3217c1f722..75ff770c42 100644 --- a/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml +++ b/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml @@ -1,5 +1,5 @@ .row.exchange-supplied-products{'ng-init' => 'initializeExchangeProductsPanel(exchange)'} - .sixteen.columns.alpha.omega + .sixteen.columns.alpha.omega{ 'ng-show' => 'enterprises[exchange.enterprise_id].supplied_products.length != 0' } .exchange-load-all-variants %div {{ 'js.admin.panels.exchange_products.products_loaded' | t:{ num_of_products_loaded: enterprises[exchange.enterprise_id].supplied_products.length, total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }} From a9598c5d97f044e279e4771a1e582b1d83d96929 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Sun, 24 Nov 2019 13:46:29 +0000 Subject: [PATCH 08/16] Only show load more and load all if not all products are loaded already --- .../admin/panels/exchange_distributed_products.html.haml | 4 ++-- .../admin/panels/exchange_supplied_products.html.haml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml index 34feaff957..2554a3bcfb 100644 --- a/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml +++ b/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml @@ -3,7 +3,7 @@ .exchange-load-all-variants %div {{ 'js.admin.panels.exchange_products.products_loaded' | t:{ num_of_products_loaded: enterprises[exchange.enterprise_id].supplied_products.length, total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }} - %a{ 'ng-click' => 'loadAllExchangeProducts(exchange)' } + %a{ 'ng-click' => 'loadAllExchangeProducts(exchange)', 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages' } {{ 'js.admin.panels.exchange_products.load_all_products' | t }} .exchange-select-all-variants @@ -32,7 +32,7 @@ 'id' => 'order_cycle_outgoing_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}', 'ng-disabled' => '!order_cycle.editable_variants_for_outgoing_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_outgoing_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' } {{ variant.label }} - .pagination + .pagination{ 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages'} .button{ 'ng-click' => 'loadMoreExchangeProducts(exchange)' } {{ 'js.admin.panels.exchange_products.load_more_products' | t }} .button{ 'ng-click' => 'loadAllExchangeProducts(exchange)' } diff --git a/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml index 75ff770c42..c79252d9c6 100644 --- a/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml +++ b/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml @@ -3,7 +3,7 @@ .exchange-load-all-variants %div {{ 'js.admin.panels.exchange_products.products_loaded' | t:{ num_of_products_loaded: enterprises[exchange.enterprise_id].supplied_products.length, total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }} - %a{ 'ng-click' => 'loadAllExchangeProducts(exchange)' } + %a{ 'ng-click' => 'loadAllExchangeProducts(exchange)', 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages' } {{ 'js.admin.panels.exchange_products.load_all_products' | t }} .exchange-select-all-variants @@ -33,7 +33,7 @@ 'id' => 'order_cycle_incoming_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}', 'ng-disabled' => '!order_cycle.editable_variants_for_incoming_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_incoming_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' } {{ variant.label }} - .pagination + .pagination{ 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages'} .button{ 'ng-click' => 'loadMoreExchangeProducts(exchange)' } {{ 'js.admin.panels.exchange_products.load_more_products' | t }} .button{ 'ng-click' => 'loadAllExchangeProducts(exchange)' } From 7e3b6e2b5db4b86a670be89b1da9debcf6be74c2 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Sun, 24 Nov 2019 14:52:19 +0000 Subject: [PATCH 09/16] Fix select all checkbox state in both incoming and outgoing exchanges by using the total count of variants to see if all variants are selected or not, even if not all variants are loaded --- .../order_cycles/controllers/incoming_controller.js.coffee | 2 ++ .../controllers/order_cycle_exchanges_controller.js.coffee | 3 +++ .../order_cycles/controllers/outgoing_controller.js.coffee | 5 +++++ app/views/admin/order_cycles/_exchange_form.html.haml | 6 +----- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/admin/order_cycles/controllers/incoming_controller.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/incoming_controller.js.coffee index ef72e3f0e5..ea5a4216fa 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/incoming_controller.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/incoming_controller.js.coffee @@ -13,6 +13,8 @@ angular.module('admin.orderCycles').controller 'AdminOrderCycleIncomingCtrl', ($ params = { exchange_id: exchange.id, enterprise_id: exchange.enterprise_id, order_cycle_id: $scope.order_cycle.id, incoming: true} ExchangeProduct.countVariants params, (variants_count) -> enterprise.numVariants = variants_count + $scope.setSelectAllVariantsCheckboxValue(exchange, enterprise.numVariants) + return enterprise.numVariants $scope.addSupplier = ($event) -> diff --git a/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee index eb38dee815..1a81aca9cc 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee @@ -5,6 +5,9 @@ angular.module('admin.orderCycles') $scope.supplier_enterprises = Enterprise.producer_enterprises $scope.distributor_enterprises = Enterprise.hub_enterprises + $scope.setSelectAllVariantsCheckboxValue = (exchange, totalNumberOfVariants) -> + exchange.select_all_variants = $scope.exchangeSelectedVariants(exchange) >= totalNumberOfVariants + $scope.exchangeSelectedVariants = (exchange) -> OrderCycle.exchangeSelectedVariants(exchange) diff --git a/app/assets/javascripts/admin/order_cycles/controllers/outgoing_controller.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/outgoing_controller.js.coffee index 157a723672..31aec9677f 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/outgoing_controller.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/outgoing_controller.js.coffee @@ -9,6 +9,11 @@ angular.module('admin.orderCycles').controller 'AdminOrderCycleOutgoingCtrl', ($ $scope.incomingExchangeVariantsFor = (enterprise_id) -> $filter('filterExchangeVariants')(OrderCycle.incomingExchangesVariants(), $scope.order_cycle.visible_variants_for_outgoing_exchanges[enterprise_id]) + $scope.exchangeTotalVariants = (exchange) -> + totalNumberOfVariants = $scope.incomingExchangeVariantsFor(exchange.enterprise_id).length + $scope.setSelectAllVariantsCheckboxValue(exchange, totalNumberOfVariants) + totalNumberOfVariants + $scope.addDistributor = ($event) -> $event.preventDefault() OrderCycle.addDistributor $scope.new_distributor_id diff --git a/app/views/admin/order_cycles/_exchange_form.html.haml b/app/views/admin/order_cycles/_exchange_form.html.haml index b89016c22b..267d6f242f 100644 --- a/app/views/admin/order_cycles/_exchange_form.html.haml +++ b/app/views/admin/order_cycles/_exchange_form.html.haml @@ -1,11 +1,7 @@ %tr{ ng: { class: "'#{type} #{type}-{{ exchange.enterprise_id }}'" } } %td{:class => "#{type}_name"} {{ enterprises[exchange.enterprise_id].name }} %td.products.panel-toggle.text-center{ name: "products" } - {{ exchangeSelectedVariants(exchange) }} / - - if type == 'supplier' - {{ exchangeTotalVariants(exchange) }} - - else - {{ (incomingExchangeVariantsFor(exchange.enterprise_id)).length }} + {{ exchangeSelectedVariants(exchange) }} / {{ exchangeTotalVariants(exchange) }} = t('.selected') - if type == 'supplier' %td.receival-details From 3264355f127baec601f987b7764309d599fad04e Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Sun, 24 Nov 2019 19:17:33 +0000 Subject: [PATCH 10/16] Add some basic test coverage to exchange_products_controller and exchange_products_renderer --- .../api/exchange_products_controller_spec.rb | 43 +++++++++++++------ .../exchange_products_renderer_spec.rb | 29 +++++++++++++ 2 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 spec/services/exchange_products_renderer_spec.rb diff --git a/spec/controllers/api/exchange_products_controller_spec.rb b/spec/controllers/api/exchange_products_controller_spec.rb index 86aa27dd73..50158a69e5 100644 --- a/spec/controllers/api/exchange_products_controller_spec.rb +++ b/spec/controllers/api/exchange_products_controller_spec.rb @@ -4,31 +4,46 @@ module Api describe ExchangeProductsController, type: :controller do include AuthenticationWorkflow - let!(:order_cycle) { create(:order_cycle) } - let!(:coordinator) { order_cycle.coordinator } + let(:order_cycle) { create(:order_cycle) } + let(:exchange) { order_cycle.exchanges.incoming.first } + let(:coordinator) { order_cycle.coordinator } + + let!(:renderer) { ExchangeProductsRenderer.new(order_cycle, coordinator.owner) } before do allow(controller).to receive_messages spree_current_user: coordinator.owner + allow(ExchangeProductsRenderer).to receive(:new) { renderer } + allow(renderer). + to receive(:exchange_products). + with(exchange.incoming, exchange.sender). + and_return(products_relation) end describe "#index" do - describe "for incoming exchanges" do - it "loads data" do - exchange = order_cycle.exchanges.incoming.first - spree_get :index, exchange_id: exchange.id + describe "when the product list is empty" do + let(:products_relation) { Spree::Product.where("1=0") } - expect(json_response["products"].first["supplier_name"]).to eq exchange.variants.first.product.supplier.name + it "handles it gracefully" do + spree_get :index, exchange_id: exchange.id + expect(json_response["products"].length).to eq 0 end end - describe "for outgoing exchanges" do - it "loads data" do - exchange = order_cycle.exchanges.outgoing.first - spree_get :index, exchange_id: exchange.id + describe "when a product is returned" do + let(:products_relation) { Spree::Product.where(id: exchange.variants.first.product.id) } - suppliers = [exchange.variants[0].product.supplier.name, exchange.variants[1].product.supplier.name] - expect(suppliers).to include json_response["products"].first["supplier_name"] - expect(suppliers).to include json_response["products"].second["supplier_name"] + describe "when an exchange id param is provided" do + it "uses exchange order_cycle, incoming and enterprise to fetch products" do + spree_get :index, exchange_id: exchange.id, order_cycle_id: 666, enterprise_id: 666, incoming: false + expect(json_response["products"].first["supplier_name"]).to eq exchange.variants.first.product.supplier.name + end + end + + describe "when an exchange id param is not provided" do + it "uses params order_cycle, incoming and enterprise to fetch products" do + spree_get :index, order_cycle_id: order_cycle.id, enterprise_id: exchange.sender_id, incoming: true + expect(json_response["products"].first["supplier_name"]).to eq exchange.variants.first.product.supplier.name + end end end end diff --git a/spec/services/exchange_products_renderer_spec.rb b/spec/services/exchange_products_renderer_spec.rb new file mode 100644 index 0000000000..2af3636e3d --- /dev/null +++ b/spec/services/exchange_products_renderer_spec.rb @@ -0,0 +1,29 @@ +require "spec_helper" + +describe ExchangeProductsRenderer do + let(:order_cycle) { create(:order_cycle) } + let(:coordinator) { order_cycle.coordinator } + let(:renderer) { described_class.new(order_cycle, coordinator.owner) } + + describe "#exchange_products" do + describe "for an incoming exchange" do + it "loads products" do + exchange = order_cycle.exchanges.incoming.first + products = renderer.exchange_products(true, exchange.sender) + + expect(products.first.supplier.name).to eq exchange.variants.first.product.supplier.name + end + end + + describe "for an outgoing exchange" do + it "loads products" do + exchange = order_cycle.exchanges.outgoing.first + products = renderer.exchange_products(false, exchange.receiver) + + suppliers = [exchange.variants[0].product.supplier.name, exchange.variants[1].product.supplier.name] + expect(suppliers).to include products.first.supplier.name + expect(suppliers).to include products.second.supplier.name + end + end + end +end From 99e59595b49d082ab3ad34c66731ed5200cbbe18 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Mon, 25 Nov 2019 23:22:16 +0000 Subject: [PATCH 11/16] Add spinner when loading all products in an exchange --- .../controllers/incoming_controller.js.coffee | 2 +- .../order_cycle_exchanges_controller.js.coffee | 16 ++++++++++------ .../services/exchange_product.js.coffee | 2 -- .../exchange_distributed_products.html.haml | 11 +++++++++-- .../panels/exchange_supplied_products.html.haml | 13 ++++++++++--- .../stylesheets/admin/openfoodnetwork.css.scss | 1 + .../admin/order_cycles/_exchange_form.html.haml | 4 ++-- config/locales/en.yml | 1 + 8 files changed, 34 insertions(+), 16 deletions(-) diff --git a/app/assets/javascripts/admin/order_cycles/controllers/incoming_controller.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/incoming_controller.js.coffee index ea5a4216fa..c18cc0e4a3 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/incoming_controller.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/incoming_controller.js.coffee @@ -26,6 +26,6 @@ angular.module('admin.orderCycles').controller 'AdminOrderCycleIncomingCtrl', ($ # This is only needed in Incoming exchanges as here we use supplied_products, # in Outgoing Exchanges the variants are loaded as part of the Exchange payload $scope.selectAllVariants = (exchange, selected) -> - Promise.all($scope.loadAllExchangeProducts(exchange)).then -> + $scope.loadAllExchangeProducts(exchange).then -> $scope.setExchangeVariants(exchange, $scope.suppliedVariants(exchange.enterprise_id), selected) $scope.$apply() diff --git a/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee index 1a81aca9cc..fde1436745 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_exchanges_controller.js.coffee @@ -5,6 +5,9 @@ angular.module('admin.orderCycles') $scope.supplier_enterprises = Enterprise.producer_enterprises $scope.distributor_enterprises = Enterprise.hub_enterprises + $scope.productsLoading = -> + RequestMonitor.loading + $scope.setSelectAllVariantsCheckboxValue = (exchange, totalNumberOfVariants) -> exchange.select_all_variants = $scope.exchangeSelectedVariants(exchange) >= totalNumberOfVariants @@ -58,15 +61,16 @@ angular.module('admin.orderCycles') $scope.loadAllExchangeProducts = (exchange) -> enterprise = $scope.enterprises[exchange.enterprise_id] - return [] if enterprise.last_page_loaded >= enterprise.num_of_pages - all_promises = [] - for page_to_load in [(enterprise.last_page_loaded + 1)..enterprise.num_of_pages] - all_promises.push $scope.loadExchangeProducts(exchange, page_to_load).$promise - all_promises + + if enterprise.last_page_loaded < enterprise.num_of_pages + for page_to_load in [(enterprise.last_page_loaded + 1)..enterprise.num_of_pages] + RequestMonitor.load $scope.loadExchangeProducts(exchange, page_to_load).$promise + + RequestMonitor.loadQueue # initialize exchange products panel if not yet done $scope.exchangeProdutsPanelInitialized = [] $scope.initializeExchangeProductsPanel = (exchange) -> return if $scope.exchangeProdutsPanelInitialized[exchange.enterprise_id] - $scope.loadExchangeProducts(exchange) + RequestMonitor.load $scope.loadExchangeProducts(exchange).$promise $scope.exchangeProdutsPanelInitialized[exchange.enterprise_id] = true diff --git a/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee b/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee index 1a80c637d5..9750b0f753 100644 --- a/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/services/exchange_product.js.coffee @@ -5,11 +5,9 @@ angular.module('admin.orderCycles').factory('ExchangeProduct', ($resource) -> }) { ExchangeProductResource: ExchangeProductResource - loaded: false index: (params={}, callback=null) -> ExchangeProductResource.index params, (data) => - @loaded = true (callback || angular.noop)(data.products, data.pagination.pages, data.pagination.results) countVariants: (params={}, callback=null) -> diff --git a/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml index 2554a3bcfb..6048fcb4f5 100644 --- a/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml +++ b/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml @@ -15,7 +15,7 @@ 'id' => 'order_cycle_outgoing_exchange_{{ $parent.$index }}_select_all_variants' } {{ 'js.admin.panels.exchange_products.select_all_products' | t:{ total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }} - .exchange-products + .exchange-products{ 'ng-hide' => 'productsLoading()' } -# Scope product list based on permissions the current user has to view variants in this exchange .exchange-product{'ng-repeat' => 'product in enterprises[exchange.enterprise_id].supplied_products | filter:visibleProducts:exchange:order_cycle.visible_variants_for_outgoing_exchanges' } .exchange-product-details @@ -32,8 +32,15 @@ 'id' => 'order_cycle_outgoing_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}', 'ng-disabled' => '!order_cycle.editable_variants_for_outgoing_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_outgoing_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' } {{ variant.label }} - .pagination{ 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages'} + + .pagination{ 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages && !productsLoading()'} .button{ 'ng-click' => 'loadMoreExchangeProducts(exchange)' } {{ 'js.admin.panels.exchange_products.load_more_products' | t }} .button{ 'ng-click' => 'loadAllExchangeProducts(exchange)' } {{ 'js.admin.panels.exchange_products.load_all_products' | t }} + + .sixteen.columns.alpha#loading{ 'ng-show' => 'productsLoading()' } + %br + %img.spinner{ src: "/assets/spinning-circles.svg" } + %h1 + {{ 'js.admin.panels.exchange_products.loading_products' | t }} diff --git a/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml index c79252d9c6..246a0d5f50 100644 --- a/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml +++ b/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml @@ -3,7 +3,7 @@ .exchange-load-all-variants %div {{ 'js.admin.panels.exchange_products.products_loaded' | t:{ num_of_products_loaded: enterprises[exchange.enterprise_id].supplied_products.length, total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }} - %a{ 'ng-click' => 'loadAllExchangeProducts(exchange)', 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages' } + %a{ 'ng-click' => 'loadAllExchangeProducts(exchange)', 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages' } {{ 'js.admin.panels.exchange_products.load_all_products' | t }} .exchange-select-all-variants @@ -15,7 +15,7 @@ 'id' => 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants' } {{ 'js.admin.panels.exchange_products.select_all_products' | t:{ total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }} - .exchange-products + .exchange-products{ 'ng-hide' => 'productsLoading()' } -# No need to scope product list based on permissions, because if an incoming exchange is visible, -# then all of the variants within it should be visible. May change in the future? .exchange-product{'ng-repeat' => 'product in enterprises[exchange.enterprise_id].supplied_products'} @@ -33,8 +33,15 @@ 'id' => 'order_cycle_incoming_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}', 'ng-disabled' => '!order_cycle.editable_variants_for_incoming_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_incoming_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' } {{ variant.label }} - .pagination{ 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages'} + + .pagination{ 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages && !productsLoading()'} .button{ 'ng-click' => 'loadMoreExchangeProducts(exchange)' } {{ 'js.admin.panels.exchange_products.load_more_products' | t }} .button{ 'ng-click' => 'loadAllExchangeProducts(exchange)' } {{ 'js.admin.panels.exchange_products.load_all_products' | t }} + + .sixteen.columns.alpha#loading{ 'ng-show' => 'productsLoading()' } + %br + %img.spinner{ src: "/assets/spinning-circles.svg" } + %h1 + {{ 'js.admin.panels.exchange_products.loading_products' | t }} diff --git a/app/assets/stylesheets/admin/openfoodnetwork.css.scss b/app/assets/stylesheets/admin/openfoodnetwork.css.scss index f26fbc992f..99f4a849bb 100644 --- a/app/assets/stylesheets/admin/openfoodnetwork.css.scss +++ b/app/assets/stylesheets/admin/openfoodnetwork.css.scss @@ -213,6 +213,7 @@ table#listing_enterprise_groups { #loading { text-align: center; img.spinner { + border: 0px; width: 100px; height: 100px; } diff --git a/app/views/admin/order_cycles/_exchange_form.html.haml b/app/views/admin/order_cycles/_exchange_form.html.haml index 267d6f242f..aecadde20d 100644 --- a/app/views/admin/order_cycles/_exchange_form.html.haml +++ b/app/views/admin/order_cycles/_exchange_form.html.haml @@ -31,10 +31,10 @@ - if type == 'supplier' %tr.panel-row{ object: "exchange", panels: "{products: 'exchange_supplied_products'}", - locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,selectAllVariants,suppliedVariants,removeDistributionOfVariant,initializeExchangeProductsPanel,loadMoreExchangeProducts,loadAllExchangeProducts", + locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,selectAllVariants,suppliedVariants,removeDistributionOfVariant,initializeExchangeProductsPanel,loadMoreExchangeProducts,loadAllExchangeProducts,productsLoading", colspan: 4 } - if type == 'distributor' %tr.panel-row{ object: "exchange", panels: "{products: 'exchange_distributed_products', tags: 'exchange_tags'}", - locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,incomingExchangeVariantsFor,variantSuppliedToOrderCycle,initializeExchangeProductsPanel,loadMoreExchangeProducts,loadAllExchangeProducts", + locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,incomingExchangeVariantsFor,variantSuppliedToOrderCycle,initializeExchangeProductsPanel,loadMoreExchangeProducts,loadAllExchangeProducts,productsLoading", colspan: 5 } diff --git a/config/locales/en.yml b/config/locales/en.yml index 8bb7d33cd1..d617a41c58 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2565,6 +2565,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using load_all_products: "Load All Products" select_all_products: "Select All %{total_number_of_products} Products" products_loaded: "%{num_of_products_loaded} of %{total_number_of_products} Products Loaded" + loading_products: "Loading Products" tag_rules: shipping_method_tagged_top: "Shipping methods tagged" shipping_method_tagged_bottom: "are:" From 7ad895137583fa0dd225fcb9a84a0f91253a849c Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Tue, 26 Nov 2019 11:01:56 +0000 Subject: [PATCH 12/16] DRY exchange products templates by extracting header and footer content to partial templates --- .../exchange_distributed_products.html.haml | 19 ++---------------- .../exchange_products_panel_footer.html.haml | 11 ++++++++++ .../exchange_products_panel_header.html.haml | 5 +++++ .../exchange_supplied_products.html.haml | 20 ++----------------- 4 files changed, 20 insertions(+), 35 deletions(-) create mode 100644 app/assets/javascripts/templates/admin/panels/exchange_products_panel_footer.html.haml create mode 100644 app/assets/javascripts/templates/admin/panels/exchange_products_panel_header.html.haml diff --git a/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml index 6048fcb4f5..d26bc2346c 100644 --- a/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml +++ b/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml @@ -1,10 +1,6 @@ .row.exchange-distributed-products{'ng-init' => 'initializeExchangeProductsPanel(exchange)'} .sixteen.columns.alpha.omega{ 'ng-show' => 'enterprises[exchange.enterprise_id].supplied_products.length != 0' } - .exchange-load-all-variants - %div - {{ 'js.admin.panels.exchange_products.products_loaded' | t:{ num_of_products_loaded: enterprises[exchange.enterprise_id].supplied_products.length, total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }} - %a{ 'ng-click' => 'loadAllExchangeProducts(exchange)', 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages' } - {{ 'js.admin.panels.exchange_products.load_all_products' | t }} + %div{ 'ng-include' => "'admin/panels/exchange_products_panel_header.html'" } .exchange-select-all-variants %label @@ -16,7 +12,6 @@ {{ 'js.admin.panels.exchange_products.select_all_products' | t:{ total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }} .exchange-products{ 'ng-hide' => 'productsLoading()' } - -# Scope product list based on permissions the current user has to view variants in this exchange .exchange-product{'ng-repeat' => 'product in enterprises[exchange.enterprise_id].supplied_products | filter:visibleProducts:exchange:order_cycle.visible_variants_for_outgoing_exchanges' } .exchange-product-details %label @@ -33,14 +28,4 @@ 'ng-disabled' => '!order_cycle.editable_variants_for_outgoing_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_outgoing_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' } {{ variant.label }} - .pagination{ 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages && !productsLoading()'} - .button{ 'ng-click' => 'loadMoreExchangeProducts(exchange)' } - {{ 'js.admin.panels.exchange_products.load_more_products' | t }} - .button{ 'ng-click' => 'loadAllExchangeProducts(exchange)' } - {{ 'js.admin.panels.exchange_products.load_all_products' | t }} - - .sixteen.columns.alpha#loading{ 'ng-show' => 'productsLoading()' } - %br - %img.spinner{ src: "/assets/spinning-circles.svg" } - %h1 - {{ 'js.admin.panels.exchange_products.loading_products' | t }} + %div{ 'ng-include' => "'admin/panels/exchange_products_panel_footer.html'" } diff --git a/app/assets/javascripts/templates/admin/panels/exchange_products_panel_footer.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_products_panel_footer.html.haml new file mode 100644 index 0000000000..b15b8a6d0a --- /dev/null +++ b/app/assets/javascripts/templates/admin/panels/exchange_products_panel_footer.html.haml @@ -0,0 +1,11 @@ +.pagination{ 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages && !productsLoading()'} + .button{ 'ng-click' => 'loadMoreExchangeProducts(exchange)' } + {{ 'js.admin.panels.exchange_products.load_more_products' | t }} + .button{ 'ng-click' => 'loadAllExchangeProducts(exchange)' } + {{ 'js.admin.panels.exchange_products.load_all_products' | t }} + +.sixteen.columns.alpha#loading{ 'ng-show' => 'productsLoading()' } + %br + %img.spinner{ src: "/assets/spinning-circles.svg" } + %h1 + {{ 'js.admin.panels.exchange_products.loading_products' | t }} diff --git a/app/assets/javascripts/templates/admin/panels/exchange_products_panel_header.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_products_panel_header.html.haml new file mode 100644 index 0000000000..5d08888456 --- /dev/null +++ b/app/assets/javascripts/templates/admin/panels/exchange_products_panel_header.html.haml @@ -0,0 +1,5 @@ +.exchange-load-all-variants + %div + {{ 'js.admin.panels.exchange_products.products_loaded' | t:{ num_of_products_loaded: enterprises[exchange.enterprise_id].supplied_products.length, total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }} + %a{ 'ng-click' => 'loadAllExchangeProducts(exchange)', 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages' } + {{ 'js.admin.panels.exchange_products.load_all_products' | t }} diff --git a/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml index 246a0d5f50..91747d30ce 100644 --- a/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml +++ b/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml @@ -1,10 +1,6 @@ .row.exchange-supplied-products{'ng-init' => 'initializeExchangeProductsPanel(exchange)'} .sixteen.columns.alpha.omega{ 'ng-show' => 'enterprises[exchange.enterprise_id].supplied_products.length != 0' } - .exchange-load-all-variants - %div - {{ 'js.admin.panels.exchange_products.products_loaded' | t:{ num_of_products_loaded: enterprises[exchange.enterprise_id].supplied_products.length, total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }} - %a{ 'ng-click' => 'loadAllExchangeProducts(exchange)', 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages' } - {{ 'js.admin.panels.exchange_products.load_all_products' | t }} + %div{ 'ng-include' => "'admin/panels/exchange_products_panel_header.html'" } .exchange-select-all-variants %label @@ -16,8 +12,6 @@ {{ 'js.admin.panels.exchange_products.select_all_products' | t:{ total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }} .exchange-products{ 'ng-hide' => 'productsLoading()' } - -# No need to scope product list based on permissions, because if an incoming exchange is visible, - -# then all of the variants within it should be visible. May change in the future? .exchange-product{'ng-repeat' => 'product in enterprises[exchange.enterprise_id].supplied_products'} .exchange-product-details %label @@ -34,14 +28,4 @@ 'ng-disabled' => '!order_cycle.editable_variants_for_incoming_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_incoming_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' } {{ variant.label }} - .pagination{ 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages && !productsLoading()'} - .button{ 'ng-click' => 'loadMoreExchangeProducts(exchange)' } - {{ 'js.admin.panels.exchange_products.load_more_products' | t }} - .button{ 'ng-click' => 'loadAllExchangeProducts(exchange)' } - {{ 'js.admin.panels.exchange_products.load_all_products' | t }} - - .sixteen.columns.alpha#loading{ 'ng-show' => 'productsLoading()' } - %br - %img.spinner{ src: "/assets/spinning-circles.svg" } - %h1 - {{ 'js.admin.panels.exchange_products.loading_products' | t }} + %div{ 'ng-include' => "'admin/panels/exchange_products_panel_footer.html'" } From a039ef13f4d39d6aedde5c9d20d30925321d414e Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Tue, 26 Nov 2019 12:36:57 +0000 Subject: [PATCH 13/16] Add spec for exchange products controller pagination --- .../api/exchange_products_controller_spec.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/spec/controllers/api/exchange_products_controller_spec.rb b/spec/controllers/api/exchange_products_controller_spec.rb index 50158a69e5..a19ec387fd 100644 --- a/spec/controllers/api/exchange_products_controller_spec.rb +++ b/spec/controllers/api/exchange_products_controller_spec.rb @@ -46,6 +46,19 @@ module Api end end end + + describe "pagination" do + let(:exchange) { order_cycle.exchanges.outgoing.first } + let(:products_relation) { Spree::Product.includes(:variants).where("spree_variants.id": exchange.variants.map(&:id)) } + + it "paginates results" do + spree_get :index, exchange_id: exchange.id, page: 1, per_page: 1 + + expect(json_response["products"].size).to eq 1 + expect(json_response["pagination"]["results"]).to eq 2 + expect(json_response["pagination"]["pages"]).to eq 2 + end + end end end end From a104bf8efd72246509b4ebf70049bf20fe5b42df Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Tue, 26 Nov 2019 14:41:22 +0000 Subject: [PATCH 14/16] Add feature spec to validate load all and select all exchange products --- spec/features/admin/order_cycles_spec.rb | 39 ++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/spec/features/admin/order_cycles_spec.rb b/spec/features/admin/order_cycles_spec.rb index 762e2504cf..e4f83865a8 100644 --- a/spec/features/admin/order_cycles_spec.rb +++ b/spec/features/admin/order_cycles_spec.rb @@ -522,6 +522,45 @@ feature ' expect(page).not_to have_selector 'table.exchanges tr.supplier' end + describe "editing an order cycle with multiple pages of products", js: true do + let(:order_cycle) { create(:order_cycle) } + let(:supplier_enterprise) { order_cycle.exchanges.incoming.first.sender } + let!(:new_product) { create(:product, supplier: supplier_enterprise) } + + before do + stub_const("Api::ExchangeProductsController::DEFAULT_PER_PAGE", 1) + + quick_login_as_admin + visit admin_order_cycle_incoming_path(order_cycle) + expect(page).to have_content "1 / 2 selected" + + page.find("tr.supplier-#{supplier_enterprise.id} td.products").click + expect(page).to have_selector ".exchange-product-details" + + expect(page).to have_content "1 of 2 Products Loaded" + expect(page).to_not have_content new_product.name + end + + scenario "load all products" do + page.find(".exchange-load-all-variants a").click + + expect_all_products_loaded + end + + scenario "select all products" do + check "order_cycle_incoming_exchange_0_select_all_variants" + + expect_all_products_loaded + + expect(page).to have_checked_field "order_cycle_incoming_exchange_0_variants_#{new_product.variants.first.id}", disabled: false + end + + def expect_all_products_loaded + expect(page).to have_content new_product.name.upcase + expect(page).to have_content "2 of 2 Products Loaded" + end + end + scenario "updating many order cycle opening/closing times at once", js: true do # Given three order cycles oc1 = create(:simple_order_cycle) From c6af55d9ae9a40ba9b7088b02c51227101d4abda Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Fri, 13 Dec 2019 11:54:35 +0000 Subject: [PATCH 15/16] Restructure exchange products panels so that OC simple form does not include header and footer (product count and pagination) of the non-simple OC form --- .../panels/exchange_products_simple.html.haml | 12 ++++++++++++ .../exchange_products_supplied_list.html.haml | 16 ++++++++++++++++ .../panels/exchange_supplied_products.html.haml | 17 +---------------- .../admin/order_cycles/_simple_form.html.haml | 2 +- 4 files changed, 30 insertions(+), 17 deletions(-) create mode 100644 app/assets/javascripts/templates/admin/panels/exchange_products_simple.html.haml create mode 100644 app/assets/javascripts/templates/admin/panels/exchange_products_supplied_list.html.haml diff --git a/app/assets/javascripts/templates/admin/panels/exchange_products_simple.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_products_simple.html.haml new file mode 100644 index 0000000000..ee9be41c8c --- /dev/null +++ b/app/assets/javascripts/templates/admin/panels/exchange_products_simple.html.haml @@ -0,0 +1,12 @@ +.row.exchange-supplied-products + .sixteen.columns.alpha.omega + .exchange-select-all-variants + %label + %input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants', + value: 1, + 'ng-model' => 'exchange.select_all_variants', + 'ng-change' => 'setExchangeVariants(exchange, suppliedVariants(exchange.enterprise_id), exchange.select_all_variants)', + 'id' => 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants' } + {{ 'admin.select_all' | t }} + + %div{ 'ng-include' => "'admin/panels/exchange_products_supplied_list.html'" } diff --git a/app/assets/javascripts/templates/admin/panels/exchange_products_supplied_list.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_products_supplied_list.html.haml new file mode 100644 index 0000000000..f5753df343 --- /dev/null +++ b/app/assets/javascripts/templates/admin/panels/exchange_products_supplied_list.html.haml @@ -0,0 +1,16 @@ +.exchange-products{ 'ng-hide' => 'productsLoading()' } + .exchange-product{'ng-repeat' => 'product in enterprises[exchange.enterprise_id].supplied_products'} + .exchange-product-details + %label + %img{'ng-src' => '{{ product.image_url }}'} + {{ product.name }} + + .exchange-product-variant{'ng-repeat' => 'variant in product.variants'} + %label + %input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}', + value: 1, + 'ng-model' => 'exchange.variants[variant.id]', + 'ofn-sync-distributions' => '{{ variant.id }}', + 'id' => 'order_cycle_incoming_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}', + 'ng-disabled' => '!order_cycle.editable_variants_for_incoming_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_incoming_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' } + {{ variant.label }} diff --git a/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml index 91747d30ce..ffc5277168 100644 --- a/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml +++ b/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml @@ -11,21 +11,6 @@ 'id' => 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants' } {{ 'js.admin.panels.exchange_products.select_all_products' | t:{ total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }} - .exchange-products{ 'ng-hide' => 'productsLoading()' } - .exchange-product{'ng-repeat' => 'product in enterprises[exchange.enterprise_id].supplied_products'} - .exchange-product-details - %label - %img{'ng-src' => '{{ product.image_url }}'} - {{ product.name }} - - .exchange-product-variant{'ng-repeat' => 'variant in product.variants'} - %label - %input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}', - value: 1, - 'ng-model' => 'exchange.variants[variant.id]', - 'ofn-sync-distributions' => '{{ variant.id }}', - 'id' => 'order_cycle_incoming_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}', - 'ng-disabled' => '!order_cycle.editable_variants_for_incoming_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_incoming_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' } - {{ variant.label }} + %div{ 'ng-include' => "'admin/panels/exchange_products_supplied_list.html'" } %div{ 'ng-include' => "'admin/panels/exchange_products_panel_footer.html'" } diff --git a/app/views/admin/order_cycles/_simple_form.html.haml b/app/views/admin/order_cycles/_simple_form.html.haml index 843f27ba78..3f6372175d 100644 --- a/app/views/admin/order_cycles/_simple_form.html.haml +++ b/app/views/admin/order_cycles/_simple_form.html.haml @@ -17,7 +17,7 @@ %table.exchanges %tbody{ng: {repeat: "exchange in order_cycle.incoming_exchanges"}} %tr.products - %td{ ng: { include: "'admin/panels/exchange_supplied_products.html'" } } + %td{ ng: { include: "'admin/panels/exchange_products_simple.html'" } } %br/ = label_tag t('.fees') From db7146014cf3ce04f63e9d4dd2fd71d1e4c2c6b3 Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Fri, 13 Dec 2019 12:14:41 +0000 Subject: [PATCH 16/16] Rename exchange products file names to increase clarity --- .../controllers/order_cycle_basic_controller.js.coffee | 4 ++-- ...ucts.html.haml => exchange_products_distributed.html.haml} | 0 ...roducts.html.haml => exchange_products_supplied.html.haml} | 0 app/views/admin/order_cycles/_exchange_form.html.haml | 4 ++-- 4 files changed, 4 insertions(+), 4 deletions(-) rename app/assets/javascripts/templates/admin/panels/{exchange_distributed_products.html.haml => exchange_products_distributed.html.haml} (100%) rename app/assets/javascripts/templates/admin/panels/{exchange_supplied_products.html.haml => exchange_products_supplied.html.haml} (100%) diff --git a/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_basic_controller.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_basic_controller.js.coffee index 7a01e1c5e2..ff25bc7d4b 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_basic_controller.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/order_cycle_basic_controller.js.coffee @@ -18,11 +18,11 @@ angular.module('admin.orderCycles') $scope.cancel = (destination) -> $window.location = destination - # Used in panels/exchange_supplied_products.html + # Used in panels/exchange_products_supplied.html $scope.suppliedVariants = (enterprise_id) -> Enterprise.suppliedVariants(enterprise_id) - # Used in panels/exchange_supplied_products.html and panels/exchange_distributed_products.html + # Used in panels/exchange_products_supplied.html and panels/exchange_products_distributed.html $scope.setExchangeVariants = (exchange, variants, selected) -> OrderCycle.setExchangeVariants(exchange, variants, selected) diff --git a/app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_products_distributed.html.haml similarity index 100% rename from app/assets/javascripts/templates/admin/panels/exchange_distributed_products.html.haml rename to app/assets/javascripts/templates/admin/panels/exchange_products_distributed.html.haml diff --git a/app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_products_supplied.html.haml similarity index 100% rename from app/assets/javascripts/templates/admin/panels/exchange_supplied_products.html.haml rename to app/assets/javascripts/templates/admin/panels/exchange_products_supplied.html.haml diff --git a/app/views/admin/order_cycles/_exchange_form.html.haml b/app/views/admin/order_cycles/_exchange_form.html.haml index aecadde20d..1713555840 100644 --- a/app/views/admin/order_cycles/_exchange_form.html.haml +++ b/app/views/admin/order_cycles/_exchange_form.html.haml @@ -30,11 +30,11 @@ - if type == 'supplier' %tr.panel-row{ object: "exchange", - panels: "{products: 'exchange_supplied_products'}", + panels: "{products: 'exchange_products_supplied'}", locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,selectAllVariants,suppliedVariants,removeDistributionOfVariant,initializeExchangeProductsPanel,loadMoreExchangeProducts,loadAllExchangeProducts,productsLoading", colspan: 4 } - if type == 'distributor' %tr.panel-row{ object: "exchange", - panels: "{products: 'exchange_distributed_products', tags: 'exchange_tags'}", + panels: "{products: 'exchange_products_distributed', tags: 'exchange_tags'}", locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,incomingExchangeVariantsFor,variantSuppliedToOrderCycle,initializeExchangeProductsPanel,loadMoreExchangeProducts,loadAllExchangeProducts,productsLoading", colspan: 5 }