BPUR: Can clone products

This commit is contained in:
Rob H
2013-06-12 14:58:08 +05:30
committed by Rohan Mitchell
parent 89e684a328
commit 1bd4875a6f
6 changed files with 82 additions and 2 deletions

View File

@@ -120,8 +120,22 @@ productsApp.controller('AdminBulkProductsCtrl', function($scope, $timeout, $http
})
}
$scope.cloneProduct = function(product){
dataFetcher("/admin/products/"+product.permalink_live+"/clone.json").then(function(data){
// Ideally we would use Spree's built in respond_override helper here to redirect the user after a successful clone with .json in the accept headers
// However, at the time of writing there appears to be an issue which causes the repond_with block in the destroy action of Spree::Admin::Product to break
// when a respond_overrride for the clone action is used.
var id = data.product.id;
dataFetcher("/admin/products/bulk_index.json?q[id_eq]="+id).then(function(data){
var newProduct = data[0];
newProduct.variants = toObjectWithIDKeys(newProduct.variants)
$scope.products[newProduct.id] = newProduct;
});
});
}
$scope.hasVariants = function(product){
return !angular.equals(product.variants,{});
return Object.keys(product.variants).length > 0;
}
$scope.updateProducts = function(productsToSubmit){
@@ -135,6 +149,7 @@ productsApp.controller('AdminBulkProductsCtrl', function($scope, $timeout, $http
data = toObjectWithIDKeys(data);
if (angular.toJson($scope.products) == angular.toJson(data)){
$scope.products = data;
$scope.dirtyProducts = {};
$scope.displaySuccess();
}
else{

View File

@@ -1,7 +1,11 @@
Spree::Admin::ProductsController.class_eval do
before_filter :load_product_set, :only => :bulk_index
alias_method :location_after_save_original, :location_after_save
respond_to :json, :only => :clone
#respond_override :clone => { :json => {:success => lambda { redirect_to bulk_index_admin_products_url+"?q[id_eq]=#{@new.id}" } } }
def bulk_index
respond_to do |format|

View File

@@ -36,6 +36,7 @@
%input{ 'ng-model' => 'product.available_on', :name => 'available_on', 'ng-track-product' => 'available_on', :type => 'text' }
%td.actions
%a{ 'ng-href' => '/admin/products/{{product.permalink_live}}/edit', :class => "edit-product icon-edit no-text" }
%a{ 'ng-click' => 'cloneProduct(product)', :class => "clone-product icon-copy no-text" }
%a{ 'ng-click' => 'deleteProduct(product)', :class => "delete-product icon-trash no-text" }
%tr{ 'ng-repeat' => 'variant in product.variants' }
%td

View File

@@ -57,4 +57,22 @@ describe Spree::Admin::ProductsController do
json_response.should == [ p1r, p2r ]
end
end
context "cloning a product" do
let(:ability_user) { stub_model(Spree::LegacyUser, :has_spree_role? => true) }
it "renders the newly created product as json" do
p1 = FactoryGirl.create(:product)
p2 = FactoryGirl.create(:product)
spree_get :clone, { :format => :json, :id => p1.permalink }
json_response = JSON.parse(response.body)
json_response.keys.should == ["product"]
json_response["product"]["id"].should_not == p1.id;
json_response["product"]["name"].should == "COPY OF #{p1.name}";
json_response["product"]["available_on"].should == p1.available_on.strftime("%FT%TZ");
json_response["product"]["supplier_id"].should == p1.supplier_id;
end
end
end

View File

@@ -330,5 +330,23 @@ feature %q{
URI.parse(current_url).path.should == "/admin/products/#{v1.product.permalink}/variants/#{v1.id}/edit"
end
end
describe "using clone buttons" do
it "shows a clone button for products, which duplicates the product and adds it to the page when clicked" do
p1 = FactoryGirl.create(:product, :name => "P1")
p2 = FactoryGirl.create(:product, :name => "P2")
p3 = FactoryGirl.create(:product, :name => "P3")
login_to_admin_section
visit '/admin/products/bulk_index'
page.should have_selector "a.clone-product", :count => 3
first("a.clone-product").click
page.should have_selector "a.clone-product", :count => 4
page.should have_field "product_name", with: "COPY OF #{p1.name}"
end
end
end
end

View File

@@ -362,6 +362,30 @@ describe("AdminBulkProductsCtrl", function(){
});
});
describe("cloning products",function(){
beforeEach(function(){
ctrl('AdminBulkProductsCtrl', { $scope: scope, $timeout: timeout } );
});
it("clones products using a http get request to /admin/products/(permalink)/clone.json", function(){
scope.products = { 13: { id: 13, permalink_live: "oranges" } }
httpBackend.expectGET('/admin/products/oranges/clone.json').respond(200, { product: { id: 17, name: "new_product" } } );
httpBackend.expectGET('/admin/products/bulk_index.json?q[id_eq]=17').respond(200, [ { id: 17, name: "new_product" } ] );
scope.cloneProduct(scope.products[13]);
httpBackend.flush();
});
it("adds the newly created product to scope.products, sending variants to toObjectWithIDKeys()", function(){
spyOn(window, "toObjectWithIDKeys").andCallThrough();
scope.products = { 13: { id: 13, permalink_live: "oranges" } };
httpBackend.expectGET('/admin/products/oranges/clone.json').respond(200, { product: { id: 17, name: "new_product", variants: [ { id: 3, name: "V1" } ] } } );
httpBackend.expectGET('/admin/products/bulk_index.json?q[id_eq]=17').respond(200, [ { id: 17, name: "new_product", variants: [ { id: 3, name: "V1" } ] } ] );
scope.cloneProduct(scope.products[13]);
httpBackend.flush();
expect(toObjectWithIDKeys).toHaveBeenCalledWith([ { id: 3, name: "V1" } ])
expect(scope.products).toEqual( { 13: { id: 13, permalink_live: "oranges" }, 17: { id: 17, name: "new_product", variants: { 3: { id: 3, name: "V1" } } } } );
});
});
/*describe("directives",function(){
scope = null;