diff --git a/app/assets/javascripts/admin/bulk_product_update.js.coffee b/app/assets/javascripts/admin/bulk_product_update.js.coffee index 126c0d93dd..c7db0f1208 100644 --- a/app/assets/javascripts/admin/bulk_product_update.js.coffee +++ b/app/assets/javascripts/admin/bulk_product_update.js.coffee @@ -1,4 +1,4 @@ -productEditModule = angular.module("ofn.bulk_product_edit", ["ofn.shared_services", "ofn.shared_directives"]) +productEditModule = angular.module("ofn.bulk_product_edit", ["ngResource", "ofn.shared_services", "ofn.shared_directives"]) productEditModule.config [ "$httpProvider" @@ -7,6 +7,41 @@ productEditModule.config [ provider.defaults.headers.common["Accept"] = "application/json" ] +productEditModule.factory "Taxons", ($resource) -> + resource = $resource "/admin/taxons/search" + + return { + findByIDs: (ids) -> + resource.get { ids: ids } + + findByTerm: (term) -> + resource.get { q: term } + + cleanTaxons: (data) -> + data['taxons'].map (result) -> result + } + +productEditModule.directive "ofnTaxonAutocomplete", (Taxons) -> + # Adapted from Spree's existing taxon autocompletion + require: "ngModel" + link: (scope,element,attrs,ngModel) -> + setTimeout -> + element.select2 + placeholder: Spree.translations.taxon_placeholder + multiple: true + initSelection: (element, callback) -> + Taxons.findByIDs(element.val()).$promise.then (result) -> + callback Taxons.cleanTaxons(result) + query: (query) -> + Taxons.findByTerm(query.term).$promise.then (result) -> + query.callback { results: Taxons.cleanTaxons(result) } + formatResult: (taxon) -> + taxon.pretty_name + formatSelection: (taxon) -> + taxon.pretty_name + element.on "change", -> + scope.$apply -> + ngModel.$setViewValue element.val() productEditModule.directive "ofnDecimal", -> require: "ngModel" @@ -74,12 +109,13 @@ productEditModule.controller "AdminProductEditCtrl", [ style: {} $scope.columns = - supplier: {name: "Supplier", visible: true} - name: {name: "Name", visible: true} - unit: {name: "Unit", visible: true} - price: {name: "Price", visible: true} - on_hand: {name: "On Hand", visible: true} - available_on: {name: "Available On", visible: false} + supplier: {name: "Supplier", visible: true} + name: {name: "Name", visible: true} + unit: {name: "Unit", visible: true} + price: {name: "Price", visible: true} + on_hand: {name: "On Hand", visible: true} + taxons: {name: "Taxons", visible: false} + available_on: {name: "Available On", visible: false} $scope.variant_unit_options = [ ["Weight (g)", "weight_1"], @@ -537,6 +573,9 @@ filterSubmitProducts = (productsToFilter) -> if product.hasOwnProperty("on_hand") and filteredVariants.length == 0 #only update if no variants present filteredProduct.on_hand = product.on_hand hasUpdatableProperty = true + if product.hasOwnProperty("taxon_ids") + filteredProduct.taxon_ids = product.taxon_ids + hasUpdatableProperty = true if product.hasOwnProperty("available_on") filteredProduct.available_on = product.available_on hasUpdatableProperty = true @@ -596,4 +635,4 @@ subset = (bigArray,smallArray) -> return false if angular.toJson(bigArray).indexOf(angular.toJson(item)) == -1 return true else - return false + return false \ No newline at end of file diff --git a/app/models/spree/product_set.rb b/app/models/spree/product_set.rb index e79408d8c5..0f2ebd511e 100644 --- a/app/models/spree/product_set.rb +++ b/app/models/spree/product_set.rb @@ -9,6 +9,7 @@ class Spree::ProductSet < ModelSet # and so an explicit call to update attributes on each individual variant was required. ie: # variant.update_attributes( { price: xx.x } ) def update_attributes(attributes) + attributes[:taxon_ids] = attributes[:taxon_ids].split(',') if attributes[:taxon_ids].present? e = @collection.detect { |e| e.id.to_s == attributes[:id].to_s && !e.id.nil? } if e.nil? @klass.new(attributes).save unless @reject_if.andand.call(attributes) diff --git a/app/views/spree/admin/products/bulk_edit.html.haml b/app/views/spree/admin/products/bulk_edit.html.haml index d35a1a7742..9098ad81ba 100644 --- a/app/views/spree/admin/products/bulk_edit.html.haml +++ b/app/views/spree/admin/products/bulk_edit.html.haml @@ -92,6 +92,9 @@ %col %col{'style' => 'width: 20%;'} %col{'style' => 'width: 12%;'} + %col{'style' => 'width: 12%;'} + %col + %col %col %col %col @@ -105,8 +108,11 @@ %th{ 'ng-show' => 'columns.unit.visible' } Unit / Value %th{ 'ng-show' => 'columns.price.visible' } Price %th{ 'ng-show' => 'columns.on_hand.visible' } On Hand + %th{ 'ng-show' => 'columns.taxons.visible' } Taxons %th{ 'ng-show' => 'columns.available_on.visible' } Av. On %th.actions + %th.actions + %th.actions %tbody{ 'ng-repeat' => 'product in filteredProducts = (products | filter:query)', 'ng-class-even' => "'even'", 'ng-class-odd' => "'odd'", 'ng-show' => "$index >= perPage*(currentPage-1) && $index < perPage*currentPage" } %tr.product{ :id => "p_{{product.id}}" } %td.left-actions @@ -126,6 +132,8 @@ %td{ 'ng-show' => 'columns.on_hand.visible' } %span{ 'ng-bind' => 'product.on_hand', :name => 'on_hand', 'ng-show' => '!hasOnDemandVariants(product) && (hasVariants(product) || product.on_demand)' } %input.field{ 'ng-model' => 'product.on_hand', :name => 'on_hand', 'ofn-track-product' => 'on_hand', 'ng-hide' => 'hasVariants(product) || product.on_demand', :type => 'number' } + %td{ 'ng-show' => 'columns.taxons.visible' } + %input.fullwidth{ :type => 'text', 'ng-model' => 'product.taxon_ids', 'ofn-taxon-autocomplete' => '', 'ofn-track-product' => 'taxon_ids' } %td{ 'ng-show' => 'columns.available_on.visible' } %input{ 'ng-model' => 'product.available_on', :name => 'available_on', 'ofn-track-product' => 'available_on', 'datetimepicker' => 'product.available_on', type: "text" } %td.actions @@ -148,6 +156,7 @@ %td{ 'ng-show' => 'columns.on_hand.visible' } %input.field{ 'ng-model' => 'variant.on_hand', 'ng-change' => 'updateOnHand(product)', :name => 'variant_on_hand', 'ng-hide' => 'variant.on_demand', 'ofn-track-variant' => 'on_hand', :type => 'number' } %span{ 'ng-bind' => 'variant.on_hand', :name => 'variant_on_hand', 'ng-show' => 'variant.on_demand' } + %td{ 'ng-show' => 'columns.taxons.visible' } %td{ 'ng-show' => 'columns.available_on.visible' } %td.actions %a{ 'ng-click' => 'editWarn(product,variant)', :class => "edit-variant icon-edit no-text", 'ng-show' => "variantSaved(variant)" } diff --git a/app/views/spree/api/products/bulk_show.v1.rabl b/app/views/spree/api/products/bulk_show.v1.rabl index 1e7cf4d9ea..d2cd23bd03 100644 --- a/app/views/spree/api/products/bulk_show.v1.rabl +++ b/app/views/spree/api/products/bulk_show.v1.rabl @@ -2,6 +2,7 @@ object @product attributes :id, :name, :variant_unit, :variant_unit_scale, :variant_unit_name, :on_demand # Infinity is not a valid JSON object, but Rails encodes it anyway +node( :taxon_ids ) { |p| p.taxons.map{ |t| t.id }.join(",") } node( :on_hand ) { |p| p.on_hand.nil? ? 0 : p.on_hand.to_f.finite? ? p.on_hand : "On demand" } node( :price ) { |p| p.price.nil? ? '0.0' : p.price } diff --git a/spec/javascripts/unit/bulk_product_update_spec.js.coffee b/spec/javascripts/unit/bulk_product_update_spec.js.coffee index 58a5ce1941..4621f9a5c7 100644 --- a/spec/javascripts/unit/bulk_product_update_spec.js.coffee +++ b/spec/javascripts/unit/bulk_product_update_spec.js.coffee @@ -1410,3 +1410,28 @@ describe "converting arrays of objects with ids to an object with ids as keys", expect(toObjectWithIDKeys).toHaveBeenCalledWith [id: 17] expect(toObjectWithIDKeys).not.toHaveBeenCalledWith {12: {id: 12}} + +describe "Taxons service", -> + Taxons = $httpBackend = $resource = null + + beforeEach -> + module "ofn.bulk_product_edit" + + beforeEach inject (_Taxons_, _$resource_, _$httpBackend_) -> + Taxons = _Taxons_ + $resource = _$resource_ + $httpBackend = _$httpBackend_ + + it "calling findByIDs makes a http request", -> + response = { taxons: "list of taxons by id" } + $httpBackend.expectGET("/admin/taxons/search?ids=1,2").respond 200, response + taxons = Taxons.findByIDs("1,2") + $httpBackend.flush() + expect(angular.equals(taxons,response)).toBe true + + it "calling findByTerm makes a http request", -> + response = { taxons: "list of taxons by term" } + $httpBackend.expectGET("/admin/taxons/search?q=lala").respond 200, response + taxons = Taxons.findByTerm("lala") + $httpBackend.flush() + expect(angular.equals(taxons,response)).toBe true \ No newline at end of file