From 5db0d839fa405d67bc2d1dfd3de9803992a85073 Mon Sep 17 00:00:00 2001 From: Rob H Date: Sat, 8 Jun 2013 17:21:54 +0530 Subject: [PATCH] BPUR: can delete products --- .../javascripts/admin/bulk_product_update.js | 29 +++++++++++++++++-- .../spree/admin/products/bulk_index.html.haml | 3 ++ app/views/spree/admin/products/bulk_index.rep | 1 + spec/controllers/product_controller_spec.rb | 6 ++-- .../admin/bulk_product_update_spec.rb | 24 +++++++++++++++ .../unit/bulk_product_update_spec.js | 11 +++---- 6 files changed, 64 insertions(+), 10 deletions(-) diff --git a/app/assets/javascripts/admin/bulk_product_update.js b/app/assets/javascripts/admin/bulk_product_update.js index 17e9407b60..ef3598a7a6 100644 --- a/app/assets/javascripts/admin/bulk_product_update.js +++ b/app/assets/javascripts/admin/bulk_product_update.js @@ -90,7 +90,7 @@ productsApp.controller('AdminBulkProductsCtrl', function($scope, $timeout, $http $scope.refreshProducts = function(){ dataFetcher('/admin/products/bulk_index.json').then(function(data){ - $scope.products = angular.copy(data); + $scope.products = toObjectWithIDKeys(data); }); }; @@ -98,6 +98,17 @@ productsApp.controller('AdminBulkProductsCtrl', function($scope, $timeout, $http product.on_hand = onHand(product); } + $scope.deleteProduct = function(product){ + $http({ + method: 'DELETE', + url: '/admin/products/'+product.permalink_live+".js" + }) + .success(function(data,status,headers,config){ + delete $scope.products[product.id] + delete $scope.dirtyProducts[product.id] + }) + } + $scope.updateProducts = function(productsToSubmit){ $scope.displayUpdating(); $http({ @@ -106,9 +117,9 @@ productsApp.controller('AdminBulkProductsCtrl', function($scope, $timeout, $http data: productsToSubmit }) .success(function(data){ + data = toObjectWithIDKeys(data); if (angular.toJson($scope.products) == angular.toJson(data)){ - $scope.products = angular.copy(data); - $scope.cleanProducts = angular.copy(data); + $scope.products = data; $scope.displaySuccess(); } else{ @@ -230,4 +241,16 @@ function addDirtyProperty(dirtyObjects, objectID, propertyName, propertyValue){ function removeCleanProperty(dirtyObjects, objectID, propertyName){ if (dirtyObjects.hasOwnProperty(objectID) && dirtyObjects[objectID].hasOwnProperty(propertyName)) delete dirtyObjects[objectID][propertyName]; if (dirtyObjects.hasOwnProperty(objectID) && Object.keys(dirtyObjects[objectID]).length <= 1) delete dirtyObjects[objectID]; +} + +function toObjectWithIDKeys(array){ + object = {}; + if (array instanceof Array){ + for (i in array){ + if (array[i].hasOwnProperty("id")){ + object[array[i].id] = array[i]; + } + } + } + return object; } \ No newline at end of file diff --git a/app/views/spree/admin/products/bulk_index.html.haml b/app/views/spree/admin/products/bulk_index.html.haml index 4fbcf6217f..f4e1547859 100644 --- a/app/views/spree/admin/products/bulk_index.html.haml +++ b/app/views/spree/admin/products/bulk_index.html.haml @@ -20,6 +20,7 @@ %th Price %th On Hand %th Av. On + %th.actions %tbody{ 'ng-repeat' => 'product in products | filter:query' } %tr %td @@ -33,6 +34,8 @@ %input.field{ 'ng-model' => 'product.on_hand', :name => 'on_hand', 'ng-track-product' => 'on_hand', 'ng-show' => 'product.variants.length == 0', :type => 'number' } %td %input{ 'ng-model' => 'product.available_on', :name => 'available_on', 'ng-track-product' => 'available_on', :type => 'text' } + %td.actions + %a{ 'ng-click' => 'deleteProduct(product)', :class => "delete-product icon-trash no-text" } %tr{ 'ng-repeat' => 'variant in product.variants' } %td {{ variant.options_text }} diff --git a/app/views/spree/admin/products/bulk_index.rep b/app/views/spree/admin/products/bulk_index.rep index 88c4163954..9071e4abff 100644 --- a/app/views/spree/admin/products/bulk_index.rep +++ b/app/views/spree/admin/products/bulk_index.rep @@ -11,4 +11,5 @@ r.list_of :products, @collection do r.element :price r.element :on_hand end + r.element :permalink_live, Proc.new{ |product| product.permalink } end \ No newline at end of file diff --git a/spec/controllers/product_controller_spec.rb b/spec/controllers/product_controller_spec.rb index 1b7aafe5c9..a12e922bc3 100644 --- a/spec/controllers/product_controller_spec.rb +++ b/spec/controllers/product_controller_spec.rb @@ -38,7 +38,8 @@ describe Spree::Admin::ProductsController do { "id" => v11.id, "options_text" => v11.options_text, "price" => v11.price.to_s, "on_hand" => v11.on_hand }, { "id" => v12.id, "options_text" => v12.options_text, "price" => v12.price.to_s, "on_hand" => v12.on_hand }, { "id" => v13.id, "options_text" => v13.options_text, "price" => v13.price.to_s, "on_hand" => v13.on_hand } - ] + ], + "permalink_live" => p1.permalink } p2r = { "id" => p2.id, @@ -49,7 +50,8 @@ describe Spree::Admin::ProductsController do "on_hand" => v21.on_hand, "variants" => [ #ordered by id { "id" => v21.id, "options_text" => v21.options_text, "price" => v21.price.to_s, "on_hand" => v21.on_hand } - ] + ], + "permalink_live" => p2.permalink } json_response = JSON.parse(response.body) json_response.should == [ p1r, p2r ] diff --git a/spec/features/admin/bulk_product_update_spec.rb b/spec/features/admin/bulk_product_update_spec.rb index 3fd26e0da9..84a3564d1e 100644 --- a/spec/features/admin/bulk_product_update_spec.rb +++ b/spec/features/admin/bulk_product_update_spec.rb @@ -255,4 +255,28 @@ feature %q{ click_button 'Update' page.find("span#update-status-message").should have_content "Update complete" end + + describe "using action buttons" do + describe "using delete buttons" do + it "shows a delete button for products, which deletes the appropriate product when clicked" do + p1 = FactoryGirl.create(:product) + p2 = FactoryGirl.create(:product) + p3 = FactoryGirl.create(:product) + login_to_admin_section + + visit '/admin/products/bulk_index' + + page.should have_selector "a.delete-product", :count => 3 + + first("a.delete-product").click + + page.should have_selector "a.delete-product", :count => 2 + #page.should have_selector "div.flash.notice", text: "Product has been deleted." + + visit '/admin/products/bulk_index' + + page.should have_selector "a.delete-product", :count => 2 + end + end + end end \ No newline at end of file diff --git a/spec/javascripts/unit/bulk_product_update_spec.js b/spec/javascripts/unit/bulk_product_update_spec.js index 0d999eee65..6e958e5f42 100644 --- a/spec/javascripts/unit/bulk_product_update_spec.js +++ b/spec/javascripts/unit/bulk_product_update_spec.js @@ -206,11 +206,12 @@ describe("AdminBulkProductsCtrl", function(){ expect(scope.suppliers).toEqual("list of suppliers"); }); - it("gets a list of products", function(){ + it("gets a list of products which is then passed to toObjectWithIDKeys()", function(){ httpBackend.expectGET('/admin/products/bulk_index.json').respond("list of products"); + spyOn(window, "toObjectWithIDKeys").andReturn("product object with ids as keys") scope.refreshProducts(); httpBackend.flush(); - expect(scope.products).toEqual("list of products"); + expect(scope.products).toEqual("product object with ids as keys"); }); }); @@ -289,9 +290,9 @@ describe("AdminBulkProductsCtrl", function(){ it("runs displaySuccess() when post returns success",function(){ spyOn(scope, "displaySuccess"); - scope.products = "updated list of products"; - httpBackend.expectPOST('/admin/products/bulk_update').respond(200, "updated list of products"); - scope.updateProducts("updated list of products"); + scope.products = { 1: { id: 1, name: "P1" }, 2: { id: 2, name: "P2" } }; + httpBackend.expectPOST('/admin/products/bulk_update').respond(200, [ { id: 1, name: "P1" }, { id: 2, name: "P2" } ] ); + scope.updateProducts("list of dirty products"); httpBackend.flush(); expect(scope.displaySuccess).toHaveBeenCalled(); });