mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-20 04:59:16 +00:00
move url filter functionality to service ProductFiltersService
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout, $filter, $http, $window, $location, $httpParamSerializer, BulkProducts, DisplayProperties, DirtyProducts, VariantUnitManager, StatusMessage, producers, Taxons, Columns, tax_categories, RequestMonitor, SortOptions, ErrorsParser) ->
|
||||
angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout, $filter, $http, $window, $location, BulkProducts, DisplayProperties, DirtyProducts, VariantUnitManager, StatusMessage, producers, Taxons, Columns, tax_categories, RequestMonitor, SortOptions, ErrorsParser, ProductFiltersService) ->
|
||||
$scope.StatusMessage = StatusMessage
|
||||
|
||||
$scope.columns = Columns.columns
|
||||
@@ -14,11 +14,13 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
]
|
||||
|
||||
productFilters = ['producerFilter', 'categoryFilter', 'query', 'sorting', 'importDateFilter']
|
||||
$scope.producerFilter = ""
|
||||
$scope.categoryFilter = ""
|
||||
$scope.importDateFilter = ""
|
||||
$scope.query = ""
|
||||
$scope.sorting = ""
|
||||
$scope.q = {
|
||||
producerFilter: ""
|
||||
categoryFilter: ""
|
||||
importDateFilter: ""
|
||||
query: ""
|
||||
sorting: ""
|
||||
}
|
||||
|
||||
$scope.producers = producers
|
||||
$scope.taxons = Taxons.all
|
||||
@@ -30,13 +32,8 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
|
||||
$scope.sortOptions = SortOptions
|
||||
|
||||
loadFilterFromUrl = ->
|
||||
filters = $location.search()
|
||||
for filter in productFilters
|
||||
$scope[filter] = if filters[filter] then filters[filter] else ""
|
||||
|
||||
$scope.initialise = ->
|
||||
loadFilterFromUrl()
|
||||
$scope.q = ProductFiltersService.loadFromUrl($location.search())
|
||||
$scope.fetchProducts()
|
||||
|
||||
$scope.$watchCollection '[query, producerFilter, categoryFilter, importDateFilter, per_page]', ->
|
||||
@@ -50,33 +47,33 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
filters = {}
|
||||
for filter in productFilters
|
||||
filters[filter] = $scope[filter] if $scope[filter]
|
||||
|
||||
|
||||
filters
|
||||
|
||||
$scope.fetchProducts = ->
|
||||
removeClearedValues()
|
||||
params = {
|
||||
'q[name_cont]': $scope.query,
|
||||
'q[supplier_id_eq]': $scope.producerFilter,
|
||||
'q[primary_taxon_id_eq]': $scope.categoryFilter,
|
||||
'q[s]': $scope.sorting,
|
||||
import_date: $scope.importDateFilter,
|
||||
'q[name_cont]': $scope.q.query,
|
||||
'q[supplier_id_eq]': $scope.q.producerFilter,
|
||||
'q[primary_taxon_id_eq]': $scope.q.categoryFilter,
|
||||
'q[s]': $scope.q.sorting,
|
||||
import_date: $scope.q.importDateFilter,
|
||||
page: $scope.page,
|
||||
per_page: $scope.per_page
|
||||
}
|
||||
RequestMonitor.load(BulkProducts.fetch(params).$promise).then ->
|
||||
# update url with the filters used
|
||||
$location.search(generateFilter())
|
||||
$location.search(ProductFiltersService.generate($scope.q))
|
||||
$scope.resetProducts()
|
||||
|
||||
removeClearedValues = ->
|
||||
delete $scope.producerFilter if $scope.producerFilter == "0"
|
||||
delete $scope.categoryFilter if $scope.categoryFilter == "0"
|
||||
delete $scope.importDateFilter if $scope.importDateFilter == "0"
|
||||
delete $scope.q.producerFilter if $scope.q.producerFilter == "0"
|
||||
delete $scope.q.categoryFilter if $scope.q.categoryFilter == "0"
|
||||
delete $scope.q.importDateFilter if $scope.q.importDateFilter == "0"
|
||||
|
||||
$timeout ->
|
||||
if $scope.showLatestImport
|
||||
$scope.importDateFilter = $scope.importDates[1].id
|
||||
$scope.q.importDateFilter = $scope.importDates[1].id
|
||||
|
||||
$scope.resetProducts = ->
|
||||
DirtyProducts.clear()
|
||||
@@ -106,10 +103,10 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
$scope.visibleTab = tab
|
||||
|
||||
$scope.resetSelectFilters = ->
|
||||
$scope.query = ""
|
||||
$scope.producerFilter = "0"
|
||||
$scope.categoryFilter = "0"
|
||||
$scope.importDateFilter = "0"
|
||||
$scope.q.query = ""
|
||||
$scope.q.producerFilter = "0"
|
||||
$scope.q.categoryFilter = "0"
|
||||
$scope.q.importDateFilter = "0"
|
||||
$scope.fetchProducts()
|
||||
|
||||
$scope.$watch 'sortOptions', (sort) ->
|
||||
@@ -127,9 +124,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
|
||||
$scope.editWarn = (product, variant) ->
|
||||
if confirm_unsaved_changes()
|
||||
filterUrl = $httpParamSerializer(generateFilter())
|
||||
filterUrl = "?#{filterUrl}" if filterUrl isnt ""
|
||||
$window.location.href = "#{editProductUrl(product, variant)}#{filterUrl}"
|
||||
$window.location.href = ProductFiltersService.buildUrl(editProductUrl(product, variant), $scope.q)
|
||||
|
||||
$scope.toggleShowAllVariants = ->
|
||||
showVariants = !DisplayProperties.showVariants 0
|
||||
@@ -226,10 +221,10 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
data:
|
||||
products: productsToSubmit
|
||||
filters:
|
||||
'q[name_cont]': $scope.query
|
||||
'q[supplier_id_eq]': $scope.producerFilter
|
||||
'q[primary_taxon_id_eq]': $scope.categoryFilter
|
||||
import_date: $scope.importDateFilter
|
||||
'q[name_cont]': $scope.q.query
|
||||
'q[supplier_id_eq]': $scope.q.producerFilter
|
||||
'q[primary_taxon_id_eq]': $scope.q.categoryFilter
|
||||
import_date: $scope.q.importDateFilter
|
||||
page: $scope.page
|
||||
per_page: $scope.per_page
|
||||
).success((data) ->
|
||||
|
||||
@@ -5,8 +5,8 @@ angular.module("ofn.admin").directive "ofnSelect2MinSearch", ->
|
||||
minimumResultsForSearch: attrs.ofnSelect2MinSearch
|
||||
|
||||
ngModel.$formatters.push (value) ->
|
||||
# select2 populate options with a value like "number:3" or "string:category" but
|
||||
# select2('val', value) doesn't do the translation for us as one would expect
|
||||
# select2 populates options with a value like "number:3" or "string:category" but
|
||||
# select2('val', value) doesn't do the type conversion for us as one would expect
|
||||
if isNaN(value)
|
||||
element.select2('val', "string:#{value}")
|
||||
else
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
angular.module("ofn.admin").factory "ProductFiltersService", ($httpParamSerializer) ->
|
||||
new class ProductFiltersService
|
||||
productFilters: ['producerFilter', 'categoryFilter', 'query', 'sorting', 'importDateFilter']
|
||||
|
||||
loadFromUrl: (filters) ->
|
||||
loadedFilters = {}
|
||||
for filter in @productFilters
|
||||
loadedFilters[filter] = if filters[filter] then filters[filter] else ""
|
||||
|
||||
loadedFilters
|
||||
|
||||
generate: (ctrlFilters) ->
|
||||
filters = {}
|
||||
for filter in @productFilters
|
||||
filters[filter] = ctrlFilters[filter] if ctrlFilters[filter]
|
||||
|
||||
filters
|
||||
|
||||
buildUrl: (baseUrl, ctrlFilters) ->
|
||||
filterUrl = $httpParamSerializer(@generate(ctrlFilters))
|
||||
filterUrl = "?#{filterUrl}" if filterUrl isnt ""
|
||||
|
||||
"#{baseUrl}#{filterUrl}"
|
||||
@@ -5,20 +5,20 @@
|
||||
.quick_search.three.columns.alpha
|
||||
%label{ for: 'quick_filter' }
|
||||
%br
|
||||
%input.quick-search.fullwidth{ ng: {model: 'query'}, name: "quick_filter", type: 'text', placeholder: t('admin.quick_search'), "ng-keypress" => "$event.keyCode === 13 && fetchProducts()" }
|
||||
%input.quick-search.fullwidth{ ng: {model: 'q.query'}, name: "quick_filter", type: 'text', placeholder: t('admin.quick_search'), "ng-keypress" => "$event.keyCode === 13 && fetchProducts()" }
|
||||
.one.columns
|
||||
.filter_select.three.columns
|
||||
%label{ for: 'producer_filter' }= t 'producer'
|
||||
%br
|
||||
%select.fullwidth{ id: 'producer_filter', 'ofn-select2-min-search' => 5, ng: {model: 'producerFilter', options: 'producer.id as producer.name for producer in producers'} }
|
||||
%select.fullwidth{ id: 'producer_filter', 'ofn-select2-min-search' => 5, ng: {model: 'q.producerFilter', options: 'producer.id as producer.name for producer in producers'} }
|
||||
.filter_select.three.columns
|
||||
%label{ for: 'category_filter' }= t 'category'
|
||||
%br
|
||||
%select.fullwidth{ id: 'category_filter', 'ofn-select2-min-search' => 5, ng: {model: 'categoryFilter', options: 'taxon.id as taxon.name for taxon in taxons'} }
|
||||
%select.fullwidth{ id: 'category_filter', 'ofn-select2-min-search' => 5, ng: {model: 'q.categoryFilter', options: 'taxon.id as taxon.name for taxon in taxons'} }
|
||||
.filter_select.three.columns
|
||||
%label{ for: 'import_filter' } Import Date
|
||||
%br
|
||||
%select.fullwidth{ id: 'import_date_filter', 'ofn-select2-min-search' => 5, ng: {model: 'importDateFilter', init: "importDates = #{@import_dates}; showLatestImport = #{@show_latest_import}", options: 'date.id as date.name for date in importDates'} }
|
||||
%select.fullwidth{ id: 'import_date_filter', 'ofn-select2-min-search' => 5, ng: {model: 'q.importDateFilter', init: "importDates = #{@import_dates}; showLatestImport = #{@show_latest_import}", options: 'date.id as date.name for date in importDates'} }
|
||||
|
||||
.filter_clear.three.columns.omega
|
||||
%label{ for: 'clear_all_filters' }
|
||||
|
||||
@@ -246,7 +246,7 @@ describe "filtering products for submission to database", ->
|
||||
]
|
||||
|
||||
describe "AdminProductEditCtrl", ->
|
||||
$ctrl = $scope = $timeout = $httpBackend = BulkProducts = DirtyProducts = DisplayProperties = windowStub = null
|
||||
$ctrl = $scope = $timeout = $httpBackend = BulkProducts = DirtyProducts = DisplayProperties = ProductFiltersService = windowStub = null
|
||||
|
||||
beforeEach ->
|
||||
module "ofn.admin"
|
||||
@@ -258,7 +258,7 @@ describe "AdminProductEditCtrl", ->
|
||||
$provide.value 'columns', []
|
||||
null
|
||||
|
||||
beforeEach inject((_$controller_, _$timeout_, $rootScope, _$httpBackend_, _BulkProducts_, _DirtyProducts_, _DisplayProperties_) ->
|
||||
beforeEach inject((_$controller_, _$timeout_, $rootScope, _$httpBackend_, _BulkProducts_, _DirtyProducts_, _DisplayProperties_, _ProductFiltersService_) ->
|
||||
$scope = $rootScope.$new()
|
||||
$ctrl = _$controller_
|
||||
$timeout = _$timeout_
|
||||
@@ -266,8 +266,9 @@ describe "AdminProductEditCtrl", ->
|
||||
BulkProducts = _BulkProducts_
|
||||
DirtyProducts = _DirtyProducts_
|
||||
DisplayProperties = _DisplayProperties_
|
||||
ProductFiltersService = _ProductFiltersService_
|
||||
|
||||
# Stub the window object so we don't get redirected when href is updated
|
||||
# Stub the window object so we don't get redirected when href is updated
|
||||
windowStub = {navigator: {userAgent: 'foo'}, location: {href: ''}}
|
||||
|
||||
$ctrl "AdminProductEditCtrl", {$scope: $scope, $timeout: $timeout, $window: windowStub}
|
||||
@@ -282,7 +283,7 @@ describe "AdminProductEditCtrl", ->
|
||||
expect($scope.fetchProducts.calls.count()).toBe 1
|
||||
|
||||
it "gets a list of products applying filters from the url", inject ($location) ->
|
||||
query = 'lala'
|
||||
query = 'lala'
|
||||
producerFilter = 2
|
||||
categoryFilter = 5
|
||||
sorting = 'name desc'
|
||||
@@ -291,11 +292,11 @@ describe "AdminProductEditCtrl", ->
|
||||
|
||||
$scope.initialise()
|
||||
|
||||
expect($scope.query).toBe query
|
||||
expect($scope.producerFilter).toBe producerFilter
|
||||
expect($scope.categoryFilter).toBe categoryFilter
|
||||
expect($scope.sorting).toBe sorting
|
||||
expect($scope.importDateFilter).toBe importDateFilter
|
||||
expect($scope.q.query).toBe query
|
||||
expect($scope.q.producerFilter).toBe producerFilter
|
||||
expect($scope.q.categoryFilter).toBe categoryFilter
|
||||
expect($scope.q.sorting).toBe sorting
|
||||
expect($scope.q.importDateFilter).toBe importDateFilter
|
||||
|
||||
describe "fetching products", ->
|
||||
$q = null
|
||||
@@ -316,18 +317,18 @@ describe "AdminProductEditCtrl", ->
|
||||
$scope.$digest()
|
||||
expect($scope.resetProducts).toHaveBeenCalled()
|
||||
|
||||
it "updates url wihth filter after data has been received", inject ($location, $window) ->
|
||||
it "updates url with filter after data has been received", inject ($location, $window) ->
|
||||
query = 'lala'
|
||||
producerFilter = 2
|
||||
categoryFilter = 5
|
||||
sorting = 'name desc'
|
||||
importDateFilter = '2020-06-08'
|
||||
|
||||
$scope.query = query
|
||||
$scope.producerFilter = producerFilter
|
||||
$scope.categoryFilter = categoryFilter
|
||||
$scope.sorting = sorting
|
||||
$scope.importDateFilter = importDateFilter
|
||||
$scope.q.query = query
|
||||
$scope.q.producerFilter = producerFilter
|
||||
$scope.q.categoryFilter = categoryFilter
|
||||
$scope.q.sorting = sorting
|
||||
$scope.q.importDateFilter = importDateFilter
|
||||
|
||||
$scope.fetchProducts()
|
||||
$scope.$digest()
|
||||
@@ -995,14 +996,14 @@ describe "AdminProductEditCtrl", ->
|
||||
it 'should load edit product page including the selected filters', inject ($httpParamSerializer) ->
|
||||
query = 'lala'
|
||||
category = 3
|
||||
$scope.query = query
|
||||
$scope.categoryFilter = category
|
||||
$scope.q.query = query
|
||||
$scope.q.categoryFilter = category
|
||||
|
||||
# use $httpParamSerializer as it will sort parameters alphabetically
|
||||
expectedFilter = $httpParamSerializer({ query: query, categoryFilter: category })
|
||||
|
||||
$scope.editWarn(testProduct, null)
|
||||
|
||||
|
||||
expect(windowStub.location.href).toBe(
|
||||
"/admin/products/#{testProduct.permalink_live}/edit?#{expectedFilter}"
|
||||
)
|
||||
@@ -1010,13 +1011,13 @@ describe "AdminProductEditCtrl", ->
|
||||
describe "filtering products", ->
|
||||
describe "clearing filters", ->
|
||||
it "resets filter variables", ->
|
||||
$scope.query = "lala"
|
||||
$scope.producerFilter = "5"
|
||||
$scope.categoryFilter = "6"
|
||||
$scope.q.query = "lala"
|
||||
$scope.q.producerFilter = "5"
|
||||
$scope.q.categoryFilter = "6"
|
||||
$scope.resetSelectFilters()
|
||||
expect($scope.query).toBe ""
|
||||
expect($scope.producerFilter).toBeUndefined
|
||||
expect($scope.categoryFilter).toBeUndefined
|
||||
expect($scope.q.query).toBe ""
|
||||
expect($scope.q.producerFilter).toBeUndefined
|
||||
expect($scope.q.categoryFilter).toBeUndefined
|
||||
|
||||
|
||||
describe "converting arrays of objects with ids to an object with ids as keys", ->
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
describe "ProductFiltersService service", ->
|
||||
ProductFiltersService = null
|
||||
|
||||
beforeEach ->
|
||||
module "ofn.admin"
|
||||
|
||||
beforeEach inject (_ProductFiltersService_) ->
|
||||
ProductFiltersService = _ProductFiltersService_
|
||||
|
||||
describe "loadFromUrl", ->
|
||||
it "should return a hash with value populated for filters existing in parameter", ->
|
||||
producerFilter = 2
|
||||
query = 'fruit'
|
||||
|
||||
filters = ProductFiltersService.loadFromUrl(producerFilter: producerFilter, query: query)
|
||||
|
||||
expect(filters.producerFilter).toBe producerFilter
|
||||
expect(filters.query).toBe query
|
||||
|
||||
it "should return a hash with empty value for filters missing from parameter", ->
|
||||
filters = ProductFiltersService.loadFromUrl({})
|
||||
|
||||
expect(filters.producerFilter).toBe ""
|
||||
expect(filters.query).toBe ""
|
||||
expect(filters.categoryFilter).toBe ""
|
||||
expect(filters.sorting).toBe ""
|
||||
expect(filters.importDateFilter).toBe ""
|
||||
|
||||
describe "generate", ->
|
||||
it 'should filter given hash with productFilters', ->
|
||||
producerFilter = 2
|
||||
query = 'fruit'
|
||||
|
||||
filters = ProductFiltersService.generate(
|
||||
producerFilter: producerFilter, query: query, otherParam: 'otherParam'
|
||||
)
|
||||
|
||||
expect(filters.producerFilter).toBe producerFilter
|
||||
expect(filters.query).toBe query
|
||||
expect(filters.otherParam).toBe undefined
|
||||
|
||||
describe "buildUrl", ->
|
||||
it 'should return a url adding filters to the baseUrl', inject ($httpParamSerializer) ->
|
||||
query = 'lala'
|
||||
producerFilter = 2
|
||||
categoryFilter = 5
|
||||
sorting = 'name desc'
|
||||
importDateFilter = '2020-06-08'
|
||||
filters = {
|
||||
producerFilter: producerFilter
|
||||
categoryFilter: categoryFilter
|
||||
query: query
|
||||
sorting: sorting
|
||||
importDateFilter: importDateFilter
|
||||
}
|
||||
baseUrl = "openfoodnetwork.org.au"
|
||||
|
||||
url = ProductFiltersService.buildUrl(baseUrl, filters)
|
||||
|
||||
expectedFilters = $httpParamSerializer(filters)
|
||||
expect(url).toBe("#{baseUrl}?#{expectedFilters}")
|
||||
|
||||
it 'should return baseUrl if filters are empty', ->
|
||||
baseUrl = "openfoodnetwork.org.au"
|
||||
|
||||
url = ProductFiltersService.buildUrl(baseUrl, {})
|
||||
expect(url).toBe baseUrl
|
||||
|
||||
Reference in New Issue
Block a user