Feature: Filtering and sorting in Products and Accounts list pages.
This commit is contained in:
parent
811ec89c62
commit
fb8e217c81
brewman/static
@ -1,4 +1,14 @@
|
|||||||
<h2>Accounts <a href="/Account" class="btn btn-success pull-right">Add <i class="glyphicon glyphicon-plus"></i></a></h2>
|
<h2>Accounts
|
||||||
|
<div class="form-group col-md-9 pull-right">
|
||||||
|
<div class="col-md-10">
|
||||||
|
<input type="text" class="form-control" placeholder="Search: n:Name, a:Active, u:Units, g:Group, e:true for extended properties, " or ' for Quotes" ng-model="search">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-2">
|
||||||
|
<a href="/Account" class="btn btn-success btn-block">Add <i
|
||||||
|
class="glyphicon glyphicon-plus"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</h2>
|
||||||
<table class="table table-condensed table-bordered table-striped">
|
<table class="table table-condensed table-bordered table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -10,7 +20,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="item in info">
|
<tr ng-repeat="item in accounts">
|
||||||
<td><a href="{{item.Url}}">{{item.Name}}</a></td>
|
<td><a href="{{item.Url}}">{{item.Name}}</a></td>
|
||||||
<td>{{item.Type}}</td>
|
<td>{{item.Type}}</td>
|
||||||
<td>{{item.IsActive}}</td>
|
<td>{{item.IsActive}}</td>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<h2>Products
|
<h2>Products
|
||||||
<div class="form-group col-md-9 pull-right">
|
<div class="form-group col-md-9 pull-right">
|
||||||
<div class="col-md-10">
|
<div class="col-md-10">
|
||||||
<input type="text" class="form-control" placeholder="Search: n:Name, a:Active, u:Units, g:Group, e:true for extended properties, " or ' for Quotes" ng-model="search">
|
<input type="text" class="form-control" placeholder="Search: n:Name, a:Active, u:Units, t:Type and e:true for extended properties" ng-model="search">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
<a href="/Product" class="btn btn-success btn-block">Add <i
|
<a href="/Product" class="btn btn-success btn-block">Add <i
|
||||||
|
@ -67,7 +67,7 @@ var overlord = angular.module('overlord', ['overlord.directive', 'overlord.filte
|
|||||||
when('/ClosingStock', {templateUrl: '/partial/closing-stock.html', controller: ClosingStockCtrl, resolve: ClosingStockCtrl.resolve}).
|
when('/ClosingStock', {templateUrl: '/partial/closing-stock.html', controller: ClosingStockCtrl, resolve: ClosingStockCtrl.resolve}).
|
||||||
when('/ClosingStock/:date', {templateUrl: '/partial/closing-stock.html', controller: ClosingStockCtrl, resolve: ClosingStockCtrl.resolve}).
|
when('/ClosingStock/:date', {templateUrl: '/partial/closing-stock.html', controller: ClosingStockCtrl, resolve: ClosingStockCtrl.resolve}).
|
||||||
|
|
||||||
when('/Accounts', {templateUrl: '/partial/account-list.html', controller: AccountListCtrl, resolve: AccountListCtrl.resolve}).
|
when('/Accounts', {templateUrl: '/partial/account-list.html', controller: AccountListCtrl, resolve: AccountListCtrl.resolve, reloadOnSearch:false}).
|
||||||
when('/Account', {templateUrl: '/partial/account-detail.html', controller: AccountCtrl, resolve: AccountCtrl.resolve}).
|
when('/Account', {templateUrl: '/partial/account-detail.html', controller: AccountCtrl, resolve: AccountCtrl.resolve}).
|
||||||
when('/Account/:id', {templateUrl: '/partial/account-detail.html', controller: AccountCtrl, resolve: AccountCtrl.resolve}).
|
when('/Account/:id', {templateUrl: '/partial/account-detail.html', controller: AccountCtrl, resolve: AccountCtrl.resolve}).
|
||||||
|
|
||||||
|
@ -1,34 +1,20 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var ProductListCtrl = ['$scope', '$location', '$routeParams', '$filter', 'products', function ($scope, $location, $routeParams, $filter, products) {
|
var ProductListCtrl = ['$scope', '$location', '$routeParams', 'Tokenizer', 'products', function ($scope, $location, $routeParams, Tokenizer, products) {
|
||||||
$scope.search = $routeParams.q || '';
|
$scope.search = $routeParams.q || '';
|
||||||
$scope.show_extended = false;
|
$scope.show_extended = false;
|
||||||
$scope.info = products;
|
$scope.info = products;
|
||||||
|
|
||||||
$scope.isTrue = function (value) {
|
|
||||||
return !_.any(['f', 'fa', 'fal', 'fals', 'false', 'n', 'no', '0'], function (item) {
|
|
||||||
return item === value;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.$watch('search', function (newValue, oldValue) {
|
$scope.$watch('search', function (newValue, oldValue) {
|
||||||
$scope.filterProducts(newValue);
|
$scope.filterProducts(newValue);
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
$scope.comparator = {
|
$scope.comparator = {
|
||||||
'def': 'n',
|
'def': 'n',
|
||||||
'n': {'Col': 'Name', 'Comparator': function (obj, text) {
|
'n': {'Col': 'Name', 'Comparator': 'text'},
|
||||||
return obj.toLowerCase().indexOf(text) > -1;
|
'a': {'Col': 'IsActive', 'Comparator': 'boolean'},
|
||||||
}},
|
'u': {'Col': 'Units', 'Comparator': 'text'},
|
||||||
'a': {'Col': 'IsActive', 'Comparator': function (obj, text) {
|
't': {'Col': 'ProductGroup', 'Comparator': 'text'}
|
||||||
return obj === $scope.isTrue(text);
|
|
||||||
}},
|
|
||||||
'u': {'Col': 'Units', 'Comparator': function (obj, text) {
|
|
||||||
return obj.toLowerCase().indexOf(text) > -1;
|
|
||||||
}},
|
|
||||||
't': {'Col': 'ProductGroup', 'Comparator': function (obj, text) {
|
|
||||||
return obj.toLowerCase().indexOf(text) > -1;
|
|
||||||
}}
|
|
||||||
};
|
};
|
||||||
$scope.sorter = {
|
$scope.sorter = {
|
||||||
'c': 'Code',
|
'c': 'Code',
|
||||||
@ -38,34 +24,6 @@ var ProductListCtrl = ['$scope', '$location', '$routeParams', '$filter', 'produc
|
|||||||
't': 'ProductGroup',
|
't': 'ProductGroup',
|
||||||
'a': 'IsActive'
|
'a': 'IsActive'
|
||||||
};
|
};
|
||||||
$scope.parseFilterString = function (q, defaultKey, comparator, sorter) {
|
|
||||||
var re = /((([^ ]+):\s*('[^':]+'|"[^":]+"|[^ ]+))|[^ ]+[^: '"]*)/g,
|
|
||||||
matches = [],
|
|
||||||
sorting = [];
|
|
||||||
|
|
||||||
defaultKey = comparator[defaultKey || comparator.def];
|
|
||||||
var m = q.match(re);
|
|
||||||
_.forEach(m, function (item) {
|
|
||||||
item = item.trim();
|
|
||||||
if (item.indexOf(':') === -1) {
|
|
||||||
if ((item.length > 1) && (item.charAt(0) === '+' || item.charAt(0) === '-') && (item.substr(1) in sorter)) {
|
|
||||||
sorting.push(item.charAt(0) + sorter[item.substr(1)]);
|
|
||||||
} else if (item.length > 2) {
|
|
||||||
matches.push({'Col': defaultKey.Col, 'Comparator': defaultKey.Comparator, 'Value': item});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var key = item.substr(0, item.indexOf(':')).toLowerCase();
|
|
||||||
var value = item.substr(item.indexOf(':') + 1, item.length).trim().toLowerCase();
|
|
||||||
if (value.indexOf("'") !== -1 || value.indexOf('"') !== -1) {
|
|
||||||
value = value.substring(1, value.length - 1).trim();
|
|
||||||
}
|
|
||||||
if (key !== '' && value !== '' && key in comparator) {
|
|
||||||
matches.push({'Col': comparator.Col, 'Comparator': comparator[key], 'Value': item});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return {'q': matches, 'o': sorting};
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.filterProducts = _.debounce(function (q) {
|
$scope.filterProducts = _.debounce(function (q) {
|
||||||
if (q !== $scope._search) {
|
if (q !== $scope._search) {
|
||||||
@ -76,27 +34,16 @@ var ProductListCtrl = ['$scope', '$location', '$routeParams', '$filter', 'produc
|
|||||||
$location.path('/Products').search({'q': q}).replace();
|
$location.path('/Products').search({'q': q}).replace();
|
||||||
}
|
}
|
||||||
$scope.$apply(function () {
|
$scope.$apply(function () {
|
||||||
var matches = $scope.parseFilterString(q, 'n', $scope.comparator, $scope.sorter);
|
var matches = Tokenizer.parseFilterString(q, $scope.comparator, $scope.sorter);
|
||||||
$scope.show_extended = _.any(matches.q, function (item) {
|
$scope.show_extended = _.any(matches.q, function (item) {
|
||||||
return ((item.key === 'e' || item.key === 'ext') && $scope.isTrue(item.value));
|
return ((item.key === 'e' || item.key === 'ext') && $scope.isTrue(item.value));
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.products = $scope.doFilter(q, $scope.info, matches.q, matches.o);
|
$scope.products = Tokenizer.doFilter('/Products ' + q, $scope.info, matches);
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, 350);
|
}, 350);
|
||||||
$scope.doFilter = _.memoize(function (q, array, filterExpressions, sortPredicates) {
|
|
||||||
var filterCount = filterExpressions.length;
|
|
||||||
var arrayCopy = filterCount === 0 ? array : _.filter($scope.info, function (item) {
|
|
||||||
return _.every(filterExpressions, function (expression) {
|
|
||||||
return expression.Comparator(item[expression.Col], expression.Value);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
arrayCopy = sortPredicates.length === 0 ? arrayCopy : $filter('orderBy')(arrayCopy, sortPredicates);
|
|
||||||
return arrayCopy;
|
|
||||||
|
|
||||||
});
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
ProductListCtrl.resolve = {
|
ProductListCtrl.resolve = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user