mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-26 05:55:15 +00:00
Preventing shop from being changed when unsaved customer changes exist
Also making layout of filters on customer index more consistent with other pages
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
angular.module("admin.customers").controller "customersCtrl", ($scope, $q, Customers, TagRuleResource, CurrentShop, RequestMonitor, Columns, pendingChanges, shops) ->
|
||||
angular.module("admin.customers").controller "customersCtrl", ($scope, $q, $filter, Customers, TagRuleResource, CurrentShop, RequestMonitor, Columns, pendingChanges, shops) ->
|
||||
$scope.shops = shops
|
||||
$scope.CurrentShop = CurrentShop
|
||||
$scope.RequestMonitor = RequestMonitor
|
||||
$scope.submitAll = pendingChanges.submitAll
|
||||
$scope.add = Customers.add
|
||||
@@ -8,15 +7,21 @@ angular.module("admin.customers").controller "customersCtrl", ($scope, $q, Custo
|
||||
$scope.customerLimit = 20
|
||||
$scope.columns = Columns.columns
|
||||
|
||||
$scope.$watch "CurrentShop.shop", ->
|
||||
if $scope.CurrentShop.shop.id?
|
||||
Customers.index({enterprise_id: $scope.CurrentShop.shop.id}).then (data) ->
|
||||
$scope.confirmRefresh = (event) ->
|
||||
event.preventDefault() unless pendingChanges.unsavedCount() == 0 || confirm(t("unsaved_changes_warning"))
|
||||
|
||||
$scope.$watch "shop_id", ->
|
||||
if $scope.shop_id?
|
||||
CurrentShop.shop = $filter('filter')($scope.shops, {id: $scope.shop_id})[0]
|
||||
Customers.index({enterprise_id: $scope.shop_id}).then (data) ->
|
||||
pendingChanges.removeAll()
|
||||
$scope.customers_form.$setPristine()
|
||||
$scope.customers = data
|
||||
|
||||
$scope.findTags = (query) ->
|
||||
defer = $q.defer()
|
||||
params =
|
||||
enterprise_id: $scope.CurrentShop.shop.id
|
||||
enterprise_id: $scope.shop_id
|
||||
TagRuleResource.mapByTag params, (data) =>
|
||||
filtered = data.filter (tag) ->
|
||||
tag.text.toLowerCase().indexOf(query.toLowerCase()) != -1
|
||||
|
||||
@@ -7,6 +7,7 @@ angular.module("admin.indexUtils").directive "ofnSelect2", ($sanitize, $timeout,
|
||||
text: "@?"
|
||||
blank: "=?"
|
||||
filter: "=?"
|
||||
onSelecting: "=?"
|
||||
link: (scope, element, attrs, ngModel) ->
|
||||
$timeout ->
|
||||
scope.text ||= 'name'
|
||||
@@ -24,6 +25,8 @@ angular.module("admin.indexUtils").directive "ofnSelect2", ($sanitize, $timeout,
|
||||
formatResult: (item) ->
|
||||
item[scope.text]
|
||||
|
||||
element.on "select2-opening", scope.onSelecting || angular.noop
|
||||
|
||||
attrs.$observe 'disabled', (value) ->
|
||||
element.select2('enable', !value)
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ angular.module("admin.indexUtils").factory "pendingChanges", ($q, resources, Sta
|
||||
|
||||
removeAll: =>
|
||||
@pendingChanges = {}
|
||||
StatusMessage.clear()
|
||||
|
||||
|
||||
remove: (id, attr) =>
|
||||
if @pendingChanges.hasOwnProperty("#{id}")
|
||||
@@ -40,5 +42,8 @@ angular.module("admin.indexUtils").factory "pendingChanges", ($q, resources, Sta
|
||||
@errors.push error
|
||||
change.scope.error()
|
||||
|
||||
unsavedCount: ->
|
||||
Object.keys(@pendingChanges).length
|
||||
|
||||
changeCount: (objectChanges) ->
|
||||
Object.keys(objectChanges).length
|
||||
|
||||
@@ -14,21 +14,25 @@
|
||||
= admin_inject_shops
|
||||
|
||||
%div{ ng: { controller: 'customersCtrl' } }
|
||||
.row
|
||||
.five.columns.alpha
|
||||
%h3
|
||||
=t :please_select_hub
|
||||
.four.columns
|
||||
%select.select2.fullwidth#shop_id{ 'ng-model' => 'CurrentShop.shop', name: 'shop_id', 'ng-options' => 'shop as shop.name for shop in shops' }
|
||||
.seven.columns.omega
|
||||
.row.filters
|
||||
.sixteen.columns.alpha.omega
|
||||
.filter_select.five.columns.alpha
|
||||
%label{ :for => 'quick_search', ng: {class: '{disabled: !shop_id}'} }=t('admin.quick_search')
|
||||
%br
|
||||
%input.fullwidth{ :type => "text", :id => 'quick_search', ng: { model: 'quickSearch', disabled: '!shop_id' }, :placeholder => "Search by email/code..." }
|
||||
.filter_select.four.columns
|
||||
%label{ :for => 'hub_id', ng: { bind: "shop_id ? '#{t('admin.shop')}' : '#{t('admin.variant_overrides.index.select_a_shop')}'" } }
|
||||
%br
|
||||
%input.ofn-select2.fullwidth#shop_id{ 'ng-model' => 'shop_id', name: 'shop_id', data: 'shops', on: { selecting: 'confirmRefresh' } }
|
||||
.seven.columns.omega
|
||||
|
||||
.row{ 'ng-hide' => 'RequestMonitor.loading || !CurrentShop.shop.id || customers.length == 0' }
|
||||
.controls.sixteen.columns.alpha.omega
|
||||
.five.columns.alpha
|
||||
%input.fullwidth{ :type => "text", :id => 'quick_search', 'ng-model' => 'quickSearch', :placeholder => 'Quick Search' }
|
||||
.eight.columns
|
||||
%columns-dropdown{ action: "#{controller_name}_#{action_name}" }
|
||||
.row{ 'ng-if' => 'CurrentShop.shop.id && RequestMonitor.loading' }
|
||||
%hr.divider{ ng: { show: "!RequestMonitor.loading && filteredCustomers.length > 0" } }
|
||||
|
||||
.row.controls{ ng: { show: "!RequestMonitor.loading && filteredCustomers.length > 0" } }
|
||||
.thirteen.columns.alpha
|
||||
%columns-dropdown{ action: "#{controller_name}_#{action_name}" }
|
||||
|
||||
.row{ 'ng-if' => 'shop_id && RequestMonitor.loading' }
|
||||
.sixteen.columns.alpha#loading
|
||||
%img.spinner{ src: "/assets/spinning-circles.svg" }
|
||||
%h1
|
||||
|
||||
@@ -5,14 +5,16 @@ feature 'Customers' do
|
||||
include WebHelper
|
||||
|
||||
context "as an enterprise user" do
|
||||
let(:user) { create_enterprise_user }
|
||||
let(:managed_distributor) { create(:distributor_enterprise, owner: user) }
|
||||
let(:user) { create_enterprise_user(enterprise_limit: 10) }
|
||||
let(:managed_distributor1) { create(:distributor_enterprise, owner: user) }
|
||||
let(:managed_distributor2) { create(:distributor_enterprise, owner: user) }
|
||||
let(:unmanaged_distributor) { create(:distributor_enterprise) }
|
||||
|
||||
describe "using the customers index", js: true do
|
||||
let!(:customer1) { create(:customer, enterprise: managed_distributor) }
|
||||
let!(:customer2) { create(:customer, enterprise: managed_distributor) }
|
||||
let!(:customer1) { create(:customer, enterprise: managed_distributor1) }
|
||||
let!(:customer2) { create(:customer, enterprise: managed_distributor1) }
|
||||
let!(:customer3) { create(:customer, enterprise: unmanaged_distributor) }
|
||||
let!(:customer4) { create(:customer, enterprise: managed_distributor2) }
|
||||
|
||||
before do
|
||||
quick_login_as user
|
||||
@@ -21,14 +23,15 @@ feature 'Customers' do
|
||||
|
||||
it "passes the smoke test" do
|
||||
# Prompts for a hub for a list of my managed enterprises
|
||||
expect(page).to have_select2 "shop_id", with_options: [managed_distributor.name], without_options: [unmanaged_distributor.name]
|
||||
expect(page).to have_select2 "shop_id", with_options: [managed_distributor1.name,managed_distributor2.name], without_options: [unmanaged_distributor.name]
|
||||
|
||||
select2_select managed_distributor.name, from: "shop_id"
|
||||
select2_select managed_distributor1.name, from: "shop_id"
|
||||
|
||||
# Loads the right customers
|
||||
expect(page).to have_selector "tr#c_#{customer1.id}"
|
||||
expect(page).to have_selector "tr#c_#{customer2.id}"
|
||||
expect(page).to_not have_selector "tr#c_#{customer3.id}"
|
||||
expect(page).to_not have_selector "tr#c_#{customer4.id}"
|
||||
|
||||
# Searching
|
||||
fill_in "quick_search", with: customer2.email
|
||||
@@ -43,10 +46,19 @@ feature 'Customers' do
|
||||
first("div#columns-dropdown div.menu div.menu_item", text: "Email").click
|
||||
expect(page).to_not have_selector "th.email"
|
||||
expect(page).to_not have_content customer1.email
|
||||
|
||||
# Changing Shops
|
||||
select2_select managed_distributor2.name, from: "shop_id"
|
||||
|
||||
# Loads the right customers
|
||||
expect(page).to_not have_selector "tr#c_#{customer1.id}"
|
||||
expect(page).to_not have_selector "tr#c_#{customer2.id}"
|
||||
expect(page).to_not have_selector "tr#c_#{customer3.id}"
|
||||
expect(page).to have_selector "tr#c_#{customer4.id}"
|
||||
end
|
||||
|
||||
it "allows updating of attributes" do
|
||||
select2_select managed_distributor.name, from: "shop_id"
|
||||
select2_select managed_distributor1.name, from: "shop_id"
|
||||
|
||||
within "tr#c_#{customer1.id}" do
|
||||
fill_in "code", with: "new-customer-code"
|
||||
@@ -78,7 +90,7 @@ feature 'Customers' do
|
||||
|
||||
context "when a shop is selected" do
|
||||
before do
|
||||
select2_select managed_distributor.name, from: "shop_id"
|
||||
select2_select managed_distributor1.name, from: "shop_id"
|
||||
end
|
||||
|
||||
it "creates customers when the email provided is valid" do
|
||||
@@ -88,21 +100,21 @@ feature 'Customers' do
|
||||
fill_in 'email', with: "not_an_email"
|
||||
click_button 'Add Customer'
|
||||
expect(page).to have_selector "#new-customer-dialog .error", text: "Please enter a valid email address"
|
||||
}.to_not change{Customer.of(managed_distributor).count}
|
||||
}.to_not change{Customer.of(managed_distributor1).count}
|
||||
|
||||
# When an existing email is used
|
||||
expect{
|
||||
fill_in 'email', with: customer1.email
|
||||
click_button 'Add Customer'
|
||||
expect(page).to have_selector "#new-customer-dialog .error", text: "Email is associated with an existing customer"
|
||||
}.to_not change{Customer.of(managed_distributor).count}
|
||||
}.to_not change{Customer.of(managed_distributor1).count}
|
||||
|
||||
# When a new valid email is used
|
||||
expect{
|
||||
fill_in 'email', with: "new@email.com"
|
||||
click_button 'Add Customer'
|
||||
expect(page).not_to have_selector "#new-customer-dialog"
|
||||
}.to change{Customer.of(managed_distributor).count}.from(2).to(3)
|
||||
}.to change{Customer.of(managed_distributor1).count}.from(2).to(3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
describe "CustomersCtrl", ->
|
||||
scope = null
|
||||
http = null
|
||||
shops = null
|
||||
|
||||
beforeEach ->
|
||||
module('admin.customers')
|
||||
@@ -8,28 +9,46 @@ describe "CustomersCtrl", ->
|
||||
$provide.value 'columns', []
|
||||
null
|
||||
|
||||
shops = [
|
||||
{ name: "Shop 1", id: 1 }
|
||||
{ name: "Shop 2", id: 2 }
|
||||
{ name: "Shop 3", id: 3 }
|
||||
]
|
||||
|
||||
|
||||
inject ($controller, $rootScope, _CustomerResource_, $httpBackend) ->
|
||||
scope = $rootScope
|
||||
http = $httpBackend
|
||||
$controller 'customersCtrl', {$scope: scope, CustomerResource: _CustomerResource_, shops: {}}
|
||||
$controller 'customersCtrl', {$scope: scope, CustomerResource: _CustomerResource_, shops: shops}
|
||||
jasmine.addMatchers
|
||||
toDeepEqual: (util, customEqualityTesters) ->
|
||||
compare: (actual, expected) ->
|
||||
{ pass: angular.equals(actual, expected) }
|
||||
|
||||
it "has no shop pre-selected", ->
|
||||
expect(scope.CurrentShop.shop).toEqual {}
|
||||
it "has no shop pre-selected", inject (CurrentShop) ->
|
||||
expect(CurrentShop.shop).toEqual {}
|
||||
|
||||
describe "setting the shop on scope", ->
|
||||
customer = { id: 5, email: 'someone@email.com'}
|
||||
customers = [customer]
|
||||
|
||||
beforeEach ->
|
||||
http.expectGET('/admin/customers.json?enterprise_id=1').respond 200, customers
|
||||
beforeEach inject (pendingChanges) ->
|
||||
spyOn(pendingChanges, "removeAll")
|
||||
scope.customers_form = jasmine.createSpyObj('customers_form', ['$setPristine'])
|
||||
http.expectGET('/admin/customers.json?enterprise_id=3').respond 200, customers
|
||||
scope.$apply ->
|
||||
scope.CurrentShop.shop = {id: 1}
|
||||
scope.shop_id = 3
|
||||
http.flush()
|
||||
|
||||
it "sets the CurrentShop", inject (CurrentShop) ->
|
||||
expect(CurrentShop.shop).toEqual shops[2]
|
||||
|
||||
it "sets the form state to pristine", ->
|
||||
expect(scope.customers_form.$setPristine).toHaveBeenCalled()
|
||||
|
||||
it "clears all changes", inject (pendingChanges) ->
|
||||
expect(pendingChanges.removeAll).toHaveBeenCalled()
|
||||
|
||||
it "retrievs the list of customers", ->
|
||||
expect(scope.customers).toDeepEqual customers
|
||||
|
||||
@@ -38,7 +57,7 @@ describe "CustomersCtrl", ->
|
||||
email = "customer@example.org"
|
||||
newCustomer = {id: 6, email: email}
|
||||
customers.unshift(newCustomer)
|
||||
http.expectPOST('/admin/customers.json?email=' + email + '&enterprise_id=1').respond 200, newCustomer
|
||||
http.expectPOST('/admin/customers.json?email=' + email + '&enterprise_id=3').respond 200, newCustomer
|
||||
scope.add(email)
|
||||
http.flush()
|
||||
expect(scope.customers).toDeepEqual customers
|
||||
@@ -60,7 +79,7 @@ describe "CustomersCtrl", ->
|
||||
{ text: 'three' }
|
||||
]
|
||||
beforeEach ->
|
||||
http.expectGET('/admin/tag_rules/map_by_tag.json?enterprise_id=1').respond 200, tags
|
||||
http.expectGET('/admin/tag_rules/map_by_tag.json?enterprise_id=3').respond 200, tags
|
||||
|
||||
it "retrieves the tag list", ->
|
||||
promise = scope.findTags('')
|
||||
|
||||
Reference in New Issue
Block a user