mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-06 22:36:07 +00:00
Create and delete customers in admin interface
Removed Customers service and extended CustomerResource.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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'
|
||||
})
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
.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
|
||||
.three.columns
|
||||
.eight.columns
|
||||
= 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')}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user