diff --git a/app/assets/javascripts/admin/bulk_order_management.js.coffee b/app/assets/javascripts/admin/bulk_order_management.js.coffee index b2544cd0ad..db721ce10b 100644 --- a/app/assets/javascripts/admin/bulk_order_management.js.coffee +++ b/app/assets/javascripts/admin/bulk_order_management.js.coffee @@ -106,17 +106,21 @@ orderManagementModule.controller "AdminOrderMgmtCtrl", [ "$scope", "$http", "dataFetcher", "blankOption", "pendingChanges" ($scope, $http, dataFetcher, blankOption, pendingChanges) -> - now = new Date - start = new Date( now.getTime() - ( 7 * (1440 * 60 * 1000) ) - (now.getTime() - now.getTimezoneOffset() * 60 * 1000) % (1440 * 60 * 1000) ) - end = new Date( now.getTime() - (now.getTime() - now.getTimezoneOffset() * 60 * 1000) % (1440 * 60 * 1000) + ( 1 * ( 1440 * 60 * 1000 ) ) ) - $scope.lineItems = [] - $scope.confirmDelete = true - $scope.startDate = formatDate start - $scope.endDate = formatDate end - $scope.pendingChanges = pendingChanges - $scope.quickSearch = "" + $scope.initialiseVariables = -> + now = new Date + start = new Date( now.getTime() - ( 7 * (1440 * 60 * 1000) ) - (now.getTime() - now.getTimezoneOffset() * 60 * 1000) % (1440 * 60 * 1000) ) + end = new Date( now.getTime() - (now.getTime() - now.getTimezoneOffset() * 60 * 1000) % (1440 * 60 * 1000) + ( 1 * ( 1440 * 60 * 1000 ) ) ) + $scope.lineItems = [] + $scope.confirmDelete = true + $scope.startDate = formatDate start + $scope.endDate = formatDate end + $scope.pendingChanges = pendingChanges + $scope.quickSearch = "" + $scope.bulkActions = [ { name: "Delete", callback: $scope.deleteSelected } ] + $scope.selectedBulkAction = $scope.bulkActions[0] $scope.initialise = (spree_api_key) -> + $scope.initialiseVariables() authorise_api_reponse = "" dataFetcher("/api/users/authorise_api?token=" + spree_api_key).then (data) -> authorise_api_reponse = data @@ -190,7 +194,12 @@ orderManagementModule.controller "AdminOrderMgmtCtrl", [ url: "/api/orders/" + lineItem.order.number + "/line_items/" + lineItem.id ).success (data) -> $scope.lineItems.splice $scope.lineItems.indexOf(lineItem), 1 - lineItem.order.line_items.splice lineItem.order.line_items.indexOf(lineItem), 1 + + $scope.deleteSelected = -> + existingState = $scope.confirmDelete + $scope.confirmDelete = false + $scope.deleteLineItem lineItem for lineItem in $scope.lineItems when lineItem.checked + $scope.confirmDelete = existingState $scope.allBoxesChecked = -> checkedCount = $scope.lineItems.reduce (count,lineItem) -> @@ -208,9 +217,9 @@ orderManagementModule.filter "selectFilter", [ (blankOption) -> return (lineItems,selectedSupplier,selectedDistributor,selectedOrderCycle) -> filtered = [] - filtered.push line_item for line_item in lineItems when (angular.equals(selectedSupplier,blankOption()) || line_item.supplier == selectedSupplier) && - (angular.equals(selectedDistributor,blankOption()) || line_item.order.distributor == selectedDistributor) && - (angular.equals(selectedOrderCycle,blankOption()) || line_item.order.order_cycle == selectedOrderCycle) + filtered.push lineItem for lineItem in lineItems when (angular.equals(selectedSupplier,blankOption()) || lineItem.supplier == selectedSupplier) && + (angular.equals(selectedDistributor,blankOption()) || lineItem.order.distributor == selectedDistributor) && + (angular.equals(selectedOrderCycle,blankOption()) || lineItem.order.order_cycle == selectedOrderCycle) filtered ] diff --git a/app/views/spree/admin/orders/bulk_management.html.haml b/app/views/spree/admin/orders/bulk_management.html.haml index a273ffef2a..8ba7610b87 100644 --- a/app/views/spree/admin/orders/bulk_management.html.haml +++ b/app/views/spree/admin/orders/bulk_management.html.haml @@ -34,7 +34,18 @@ %label{ :for => 'quick_search' }Quick Search %br %input{ :class => "three columns alpha", :type => "text", :id => 'quick_search', 'ng-model' => 'quickSearch', :placeholder => 'Quick Search' } - .spacer{ :class => "seven columns alpha" } + .spacer{ :class => "one columns alpha" } +   + .bulk_actions{ :class => "three columns alpha" } + %div{ :class => "three columns alpha" } + %label{ :for => 'bulk_actions' }Bulk Action + %br + %select.select2{ :class => "three columns alpha", :id => 'bulk_actions', 'ng-model' => 'selectedBulkAction', 'ng-options' => 'a as a.name for a in bulkActions' } + %div{ :class => "three columns alpha" } + %label{ :for => 'bulk_execute' } + %br + %input{ :class => "three columns alpha", :value => "Run", :type => "button", :id => 'bulk_execute', 'ng-click' => 'selectedBulkAction.callback()' } + .spacer{ :class => "three columns alpha" }   %hr{ :class => "sixteen columns alpha", :style => "margin-bottom: 15px" } %div.loading{ :class => "sixteen columns alpha", 'ng-show' => 'loading' } @@ -58,7 +69,7 @@ %input{ :type => 'checkbox', 'ng-model' => "confirmDelete" } %tr.line_item{ 'ng-repeat' => 'line_item in lineItems | filter:quickSearch | selectFilter:supplierFilter:distributorFilter:orderCycleFilter:quickSearch', 'ng-class-even' => "'even'", 'ng-class-odd' => "'odd'", :id => "li_{{line_item.id}}" } %td.bulk - %input.bulk{ :type => "checkbox", 'ng-model' => 'line_item.checked' } + %input{ :type => "checkbox", :name => 'bulk', 'ng-model' => 'line_item.checked' } %td.full_name {{ line_item.order.full_name }} %td.date {{ line_item.order.completed_at }} %td.producer {{ line_item.supplier.name }} diff --git a/spec/features/admin/bulk_order_management_spec.rb b/spec/features/admin/bulk_order_management_spec.rb index 3b398ed52d..428ee521cd 100644 --- a/spec/features/admin/bulk_order_management_spec.rb +++ b/spec/features/admin/bulk_order_management_spec.rb @@ -349,7 +349,7 @@ feature %q{ end end - context "bulk actions" do + context "bulk action controls" do let!(:o1) { FactoryGirl.create(:order, state: 'complete', completed_at: Time.now ) } let!(:o2) { FactoryGirl.create(:order, state: 'complete', completed_at: Time.now ) } let!(:li1) { FactoryGirl.create(:line_item, order: o1 ) } @@ -360,15 +360,37 @@ feature %q{ end it "displays a checkbox for each line item in the list" do - page.should have_selector "tr#li_#{li1.id} input[type='checkbox'].bulk" - page.should have_selector "tr#li_#{li2.id} input[type='checkbox'].bulk" + page.should have_selector "tr#li_#{li1.id} input[type='checkbox'][name='bulk']" + page.should have_selector "tr#li_#{li2.id} input[type='checkbox'][name='bulk']" end it "displays a checkbox to which toggles the 'checked' state of all checkboxes" do check "toggle_bulk" - page.all("input[type='checkbox'].bulk").each{ |checkbox| checkbox.checked?.should == true } + page.all("input[type='checkbox'][name='bulk']").each{ |checkbox| checkbox.checked?.should == true } uncheck "toggle_bulk" - page.all("input[type='checkbox'].bulk").each{ |checkbox| checkbox.checked?.should == false } + page.all("input[type='checkbox'][name='bulk']").each{ |checkbox| checkbox.checked?.should == false } + end + + it "displays a bulk action select box with a list of actions" do + page.should have_select "bulk_actions", :options => ["Delete"] + end + + it "displays a bulk action button" do + page.should have_button "bulk_execute" + end + + context "performing actions" do + it "deletes selected items" do + page.should have_selector "tr#li_#{li1.id}", visible: true + page.should have_selector "tr#li_#{li2.id}", visible: true + within("tr#li_#{li2.id} td.bulk") do + check "bulk" + end + select "Delete", :from => "bulk_actions" + click_button "bulk_execute" + page.should have_selector "tr#li_#{li1.id}", visible: true + page.should_not have_selector "tr#li_#{li2.id}", visible: true + end end end diff --git a/spec/javascripts/unit/bulk_order_management_spec.js.coffee b/spec/javascripts/unit/bulk_order_management_spec.js.coffee index 9f3ab0d398..dd79555dc7 100644 --- a/spec/javascripts/unit/bulk_order_management_spec.js.coffee +++ b/spec/javascripts/unit/bulk_order_management_spec.js.coffee @@ -21,6 +21,7 @@ describe "AdminOrderMgmtCtrl", -> httpBackend.expectGET("/api/enterprises/managed?template=bulk_index&q[is_primary_producer_eq]=true").respond returnedSuppliers httpBackend.expectGET("/api/enterprises/managed?template=bulk_index&q[is_distributor_eq]=true").respond returnedDistributors httpBackend.expectGET("/api/order_cycles/managed").respond returnedOrderCycles + spyOn(scope, "initialiseVariables").andCallThrough() spyOn(scope, "fetchOrders").andReturn "nothing" spyOn(returnedSuppliers, "unshift") spyOn(returnedDistributors, "unshift") @@ -31,6 +32,7 @@ describe "AdminOrderMgmtCtrl", -> expect(scope.suppliers).toEqual ["list of suppliers"] expect(scope.distributors).toEqual ["list of distributors"] expect(scope.orderCycles).toEqual [ "oc1", "oc2", "oc3" ] + expect(scope.initialiseVariables.calls.length).toEqual 1 expect(scope.fetchOrders.calls.length).toEqual 1 expect(returnedSuppliers.unshift.calls.length).toEqual 1 expect(returnedDistributors.unshift.calls.length).toEqual 1 @@ -40,6 +42,7 @@ describe "AdminOrderMgmtCtrl", -> describe "fetching orders", -> beforeEach -> + scope.initialiseVariables() httpBackend.expectGET("/api/orders?template=bulk_index&q[completed_at_not_null]=true&q[completed_at_gt]=SomeDate&q[completed_at_lt]=SomeDate").respond "list of orders" it "makes a call to dataFetcher, with current start and end date parameters", -> @@ -185,7 +188,9 @@ describe "AdminOrderMgmtCtrl", -> describe "deleting a line item", -> order = line_item1 = line_item2 = null + beforeEach -> + scope.initialiseVariables() spyOn(window,"confirm").andReturn true order = { number: "R12345678", line_items: [] } line_item1 = { id: 1, order: order } @@ -197,18 +202,30 @@ describe "AdminOrderMgmtCtrl", -> scope.deleteLineItem line_item1 httpBackend.flush() - it "removes line_item from the line_items array of the relevant order object when request is 204", -> - httpBackend.expectDELETE("/api/orders/#{line_item1.order.number}/line_items/#{line_item1.id}").respond 204, "NO CONTENT" - scope.deleteLineItem line_item1 - httpBackend.flush() - expect(order.line_items).toEqual [line_item2] - it "does not remove line_item from the line_items array when request is not successful", -> httpBackend.expectDELETE("/api/orders/#{line_item1.order.number}/line_items/#{line_item1.id}").respond 404, "NO CONTENT" scope.deleteLineItem line_item1 httpBackend.flush() expect(order.line_items).toEqual [line_item1, line_item2] + describe "deleting 'checked' line items", -> + line_item1 = line_item2 = line_item3 = line_item4 = null + + beforeEach -> + line_item1 = { name: "line item 1", checked: false } + line_item2 = { name: "line item 2", checked: true } + line_item3 = { name: "line item 3", checked: false } + line_item4 = { name: "line item 4", checked: true } + scope.lineItems = [ line_item1, line_item2, line_item3, line_item4 ] + + it "calls deletedLineItem for each 'checked' line item", -> + spyOn(scope, "deleteLineItem") + scope.deleteSelected() + expect(scope.deleteLineItem).toHaveBeenCalledWith(line_item2) + expect(scope.deleteLineItem).toHaveBeenCalledWith(line_item4) + expect(scope.deleteLineItem).not.toHaveBeenCalledWith(line_item1) + expect(scope.deleteLineItem).not.toHaveBeenCalledWith(line_item3) + describe "check boxes for line items", -> line_item1 = line_item2 = null