Create and delete customers in admin interface

Removed Customers service and extended CustomerResource.
This commit is contained in:
Maikel Linke
2016-04-13 15:05:39 +10:00
parent ecd32819a6
commit 831df0b222
11 changed files with 134 additions and 73 deletions

View File

@@ -1,4 +1,4 @@
angular.module("admin.customers").controller "customersCtrl", ($scope, Customers, Columns, pendingChanges, shops) ->
angular.module("admin.customers").controller "customersCtrl", ($scope, CustomerResource, Columns, pendingChanges, shops) ->
$scope.shop = {}
$scope.shops = shops
$scope.submitAll = pendingChanges.submitAll
@@ -10,8 +10,24 @@ angular.module("admin.customers").controller "customersCtrl", ($scope, Customers
$scope.$watch "shop.id", ->
if $scope.shop.id?
Customers.loaded = false
$scope.customers = Customers.index(enterprise_id: $scope.shop.id)
$scope.customers = index {enterprise_id: $scope.shop.id}
$scope.loaded = ->
Customers.loaded
$scope.add = (email) ->
params =
enterprise_id: $scope.shop.id
email: email
CustomerResource.create params, (customer) =>
if customer.id
$scope.customers.push customer
$scope.quickSearch = customer.email
$scope.deleteCustomer = (customer) ->
params = id: customer.id
CustomerResource.destroy params, ->
i = $scope.customers.indexOf customer
$scope.customers.splice i, 1 unless i < 0
index = (params) ->
$scope.loaded = false
CustomerResource.index params, =>
$scope.loaded = true

View File

@@ -1,8 +1,17 @@
angular.module("admin.customers").factory 'CustomerResource', ($resource) ->
$resource('/admin/customers.json', {}, {
$resource('/admin/customers/:id.json', {}, {
'index':
method: 'GET'
isArray: true
params:
enterprise_id: '@enterprise_id'
'create':
method: 'POST'
params:
enterprise_id: '@enterprise_id'
email: '@email'
'destroy':
method: 'DELETE'
params:
id: '@id'
})

View File

@@ -1,16 +0,0 @@
angular.module("admin.customers").factory 'Customers', (CustomerResource) ->
new class Customers
customers: []
customers_by_id: {}
loaded: false
index: (params={}, callback=null) ->
CustomerResource.index params, (data) =>
for customer in data
@customers.push customer
@customers_by_id[customer.id] = customer
@loaded = true
(callback || angular.noop)(@customers)
@customers

View File

@@ -14,6 +14,16 @@ module Admin
end
end
def create
@customer = Customer.new(params[:customer])
if spree_current_user.enterprises.include? @customer.enterprise
@customer.save
render json: Api::Admin::CustomerSerializer.new(@customer).to_json
else
redirect_to '/unauthorized'
end
end
private
def collection

View File

@@ -101,6 +101,11 @@ class AbilityDecorator
can [:print], Spree::Order do |order|
order.user == user
end
can [:create], Customer
can [:destroy], Customer do |customer|
user.enterprises.include? customer.enterprise
end
end
def add_product_management_abilities(user)

View File

@@ -5,7 +5,7 @@
= admin_inject_shops
%div{ ng: { app: 'admin.customers', controller: 'customersCtrl' } }
.row{ ng: { hide: "loaded() && customers.length > 0" } }
.row{ ng: { hide: "loaded && customers.length > 0" } }
.five.columns.alpha
%h3
=t :please_select_hub
@@ -13,24 +13,23 @@
%select.select2.fullwidth#shop_id{ 'ng-model' => 'shop.id', name: 'shop_id', 'ng-options' => 'shop.id as shop.name for shop in shops' }
.seven.columns.omega &nbsp;
.row{ 'ng-hide' => '!loaded() || customers.length == 0' }
.row{ 'ng-hide' => '!loaded || customers.length == 0' }
.controls.sixteen.columns.alpha.omega
.five.columns.alpha
%input.fullwidth{ :type => "text", :id => 'quick_search', 'ng-model' => 'quickSearch', :placeholder => 'Quick Search' }
.five.columns &nbsp;
.three.columns &nbsp;
.eight.columns &nbsp;
= render 'admin/shared/columns_dropdown'
.row{ 'ng-if' => 'shop.id && !loaded()' }
.row{ 'ng-if' => 'shop.id && !loaded' }
.sixteen.columns.alpha#loading
%img.spinner{ src: "/assets/spinning-circles.svg" }
%h1
=t :loading_customers
.row{ :class => "sixteen columns alpha", 'ng-show' => 'loaded() && filteredCustomers.length == 0'}
.row{ :class => "sixteen columns alpha", 'ng-show' => 'loaded && filteredCustomers.length == 0'}
%h1#no_results
=t :no_customers_found
.row{ ng: { show: "loaded() && filteredCustomers.length > 0" } }
.row{ ng: { show: "loaded && filteredCustomers.length > 0" } }
%form{ name: "customers" }
%table.index#customers
%col.email{ width: "20%"}
@@ -61,3 +60,11 @@
%td.actions
%a{ 'ng-click' => "deleteCustomer(customer)", :class => "delete-customer icon-trash no-text" }
%input{ :type => "button", 'value' => 'Update', 'ng-click' => 'submitAll()' }
%form{ng: {show: "loaded", submit: 'add(newCustomerEmail)'}}
%h2= t '.add_new_customer'
.row
.five.columns.alpha
%input.fullwidth{type: "text", placeholder: t('.customer_placeholder'), ng: {model: 'newCustomerEmail'}}
.eleven.columns.omega
%input{type: "submit", value: t('.add_customer')}

View File

@@ -80,6 +80,10 @@ en:
whats_this: What's this?
customers:
index:
add_customer: "Add customer"
customer_placeholder: "customer@example.org"
inventory:
title: Inventory
description: Use this page to manage inventories for your enterprises. Any product details set here will override those set on the 'Products' page

View File

@@ -115,7 +115,7 @@ Openfoodnetwork::Application.routes.draw do
resources :inventory_items, only: [:create, :update]
resources :customers, only: [:index, :update]
resources :customers, only: [:index, :create, :update, :destroy]
resource :content

View File

@@ -94,4 +94,37 @@ describe Admin::CustomersController, type: :controller do
end
end
end
describe "create" do
let(:enterprise) { create(:distributor_enterprise) }
let(:another_enterprise) { create(:distributor_enterprise) }
def create_customer(enterprise)
spree_put :create, format: :json, customer: { email: 'new@example.com', enterprise_id: enterprise.id }
end
context "json" do
let!(:customer) { create(:customer, enterprise: enterprise) }
context "where I manage the customer's enterprise" do
before do
controller.stub spree_current_user: enterprise.owner
end
it "allows me to create the customer" do
expect { create_customer enterprise }.to change(Customer, :count).by(1)
end
end
context "where I don't manage the customer's enterprise" do
before do
controller.stub spree_current_user: another_enterprise.owner
end
it "prevents me from creating the customer" do
expect { create_customer enterprise }.to change(Customer, :count).by(0)
end
end
end
end
end

View File

@@ -1,25 +1,49 @@
describe "CustomersCtrl", ->
ctrl = null
scope = null
Customers = null
http = null
beforeEach ->
shops = "list of shops"
module('admin.customers')
inject ($controller, $rootScope, _Customers_) ->
inject ($controller, $rootScope, _CustomerResource_, $httpBackend) ->
scope = $rootScope
Customers = _Customers_
ctrl = $controller 'customersCtrl', {$scope: scope, Customers: Customers, shops: shops}
http = $httpBackend
$controller 'customersCtrl', {$scope: scope, CustomerResource: _CustomerResource_, shops: {}}
this.addMatchers
toAngularEqual: (expected) ->
return angular.equals(this.actual, expected)
it "has no shop pre-selected", ->
expect(scope.shop).toEqual {}
describe "setting the shop on scope", ->
customer = { id: 5, email: 'someone@email.com'}
customers = [customer]
beforeEach ->
spyOn(Customers, "index").andReturn "list of customers"
http.expectGET('/admin/customers.json?enterprise_id=1').respond 200, customers
scope.$apply ->
scope.shop = {id: 1}
http.flush()
it "calls Customers#index with the correct params", ->
expect(Customers.index).toHaveBeenCalledWith({enterprise_id: 1})
it "retrievs the list of customers", ->
expect(scope.customers).toAngularEqual customers
it "resets $scope.customers with the result of Customers#index", ->
expect(scope.customers).toEqual "list of customers"
describe "scope.add", ->
it "creates a new customer", ->
email = "customer@example.org"
newCustomer = {id: 6, email: email}
customers.push(newCustomer)
http.expectPOST('/admin/customers.json?email=' + email + '&enterprise_id=1').respond 200, newCustomer
scope.add(email)
http.flush()
expect(scope.customers).toAngularEqual customers
describe "scope.deleteCustomer", ->
it "deletes a customer", ->
expect(scope.customers.length).toBe 2
customer = scope.customers[0]
http.expectDELETE('/admin/customers/' + customer.id + '.json').respond 200
scope.deleteCustomer(customer)
http.flush()
expect(scope.customers.length).toBe 1
expect(scope.customers[0]).not.toAngularEqual customer

View File

@@ -1,31 +0,0 @@
describe "Customers service", ->
Customers = CustomerResource = customers = $httpBackend = null
beforeEach ->
module 'admin.customers'
inject ($q, _$httpBackend_, _Customers_, _CustomerResource_) ->
Customers = _Customers_
CustomerResource = _CustomerResource_
$httpBackend = _$httpBackend_
$httpBackend.expectGET('/admin/customers.json?enterprise_id=2').respond 200, [{ id: 5, email: 'someone@email.com'}]
describe "#index", ->
result = null
beforeEach ->
expect(Customers.loaded).toBe false
result = Customers.index(enterprise_id: 2)
$httpBackend.flush()
it "stores returned data in @customers, with ids as keys", ->
# This is super weird and freaking annoying. I think resource results have extra
# properties ($then, $promise) that cause them to not be equal to the reponse object
# provided to the expectGET clause above.
expect(Customers.customers).toEqual [ new CustomerResource({ id: 5, email: 'someone@email.com'}) ]
it "returns @customers", ->
expect(result).toEqual Customers.customers
it "sets @loaded to true", ->
expect(Customers.loaded).toBe true