Feature: Product list allows for displaying extended information and search bar shows the legend.
This commit is contained in:
parent
30442ffecb
commit
0436a5de2c
|
@ -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" ng-model="search">
|
<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>
|
||||||
<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
|
||||||
|
@ -12,18 +12,20 @@
|
||||||
<table class="table table-condensed table-bordered table-striped">
|
<table class="table table-condensed table-bordered table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Code</th>
|
<th class="text-right">Code</th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Price</th>
|
<th class="text-right">Price</th>
|
||||||
|
<th ng-if="show_extended">Yield</th>
|
||||||
<th>Type</th>
|
<th>Type</th>
|
||||||
<th>Is Active?</th>
|
<th>Is Active?</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="item in products">
|
<tr ng-repeat="item in products">
|
||||||
<td>{{item.Code}}</td>
|
<td class="text-right">{{item.Code}}</td>
|
||||||
<td><a href="{{item.Url}}">{{item.Name}} ({{item.Units}})</a></td>
|
<td><a href="{{item.Url}}">{{item.Name}} ({{show_extended ? item.Fraction + ' ' + item.FractionUnits + ' = 1 ' : ''}}{{item.Units}})</a></td>
|
||||||
<td>₹ {{item.Price}}</td>
|
<td class="text-right">{{item.Price | currency}}</td>
|
||||||
|
<td ng-if="show_extended">{{item.ProductYield * 100 | number:2}}%</td>
|
||||||
<td>{{item.ProductGroup}}</td>
|
<td>{{item.ProductGroup}}</td>
|
||||||
<td>{{item.IsActive}}</td>
|
<td>{{item.IsActive}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
var ProductListCtrl = ['$scope', '$location', '$routeParams', 'products', function ($scope, $location, $routeParams, products) {
|
var ProductListCtrl = ['$scope', '$location', '$routeParams', 'products', function ($scope, $location, $routeParams, products) {
|
||||||
$scope.search = $routeParams.q || '';
|
$scope.search = $routeParams.q || '';
|
||||||
|
$scope.show_extended = false;
|
||||||
$scope.info = products;
|
$scope.info = products;
|
||||||
var re = /((([^ ]+):\s*('[^':]+'|"[^":]+"|[^ ]+))|[^ ]+[^: '"]*)/g;
|
|
||||||
|
|
||||||
$scope.isTrue = function (value) {
|
$scope.isTrue = function (value) {
|
||||||
value = value.toLowerCase();
|
value = value.toLowerCase();
|
||||||
|
@ -16,6 +16,31 @@ var ProductListCtrl = ['$scope', '$location', '$routeParams', 'products', functi
|
||||||
$scope.filterProducts(newValue);
|
$scope.filterProducts(newValue);
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
|
$scope.parseFilterString = function (q, defaultKey) {
|
||||||
|
var re = /((([^ ]+):\s*('[^':]+'|"[^":]+"|[^ ]+))|[^ ]+[^: '"]*)/g;
|
||||||
|
var matches = [];
|
||||||
|
if (angular.isUndefined(defaultKey)) {
|
||||||
|
defaultKey = 'n';
|
||||||
|
}
|
||||||
|
var m = q.match(re);
|
||||||
|
_.forEach(m, function (item) {
|
||||||
|
item = item.toLowerCase();
|
||||||
|
if (item.indexOf(':') === -1) {
|
||||||
|
matches.push({'key': defaultKey, '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("'") !== 0 || value.indexOf('"') !== 0) {
|
||||||
|
value = value.substring(1, value.length - 2).trim();
|
||||||
|
}
|
||||||
|
if (key !== '' && value !== '') {
|
||||||
|
matches.push({'key': key, 'value': value});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return matches;
|
||||||
|
};
|
||||||
|
|
||||||
$scope.filterProducts = _.debounce(function (q) {
|
$scope.filterProducts = _.debounce(function (q) {
|
||||||
if (q !== $scope._search) {
|
if (q !== $scope._search) {
|
||||||
$scope._search = q;
|
$scope._search = q;
|
||||||
|
@ -25,35 +50,20 @@ var ProductListCtrl = ['$scope', '$location', '$routeParams', 'products', functi
|
||||||
$location.path('/Products').search({'q': q}).replace();
|
$location.path('/Products').search({'q': q}).replace();
|
||||||
}
|
}
|
||||||
$scope.$apply(function () {
|
$scope.$apply(function () {
|
||||||
$scope.products = $scope.doFilter(q);
|
var matches = $scope.parseFilterString(q);
|
||||||
|
$scope.show_extended = _.any(matches, function (item) {
|
||||||
|
return ((item.key === 'e' || item.key === 'ext') && $scope.isTrue(item.value));
|
||||||
|
});
|
||||||
|
$scope.products = $scope.doFilter(q, matches);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, 350);
|
}, 350);
|
||||||
$scope.doFilter = _.memoize(function (q) {
|
$scope.doFilter = _.memoize(function (q, matches) {
|
||||||
var matches = [], i, len;
|
var i, len = matches.length;
|
||||||
if (angular.isUndefined(q) || q === '') {
|
if (len <= 0) {
|
||||||
return $scope.info;
|
return $scope.info;
|
||||||
}
|
}
|
||||||
var m = q.match(re);
|
|
||||||
_.forEach(m, function (item) {
|
|
||||||
item = item.toLowerCase();
|
|
||||||
if (item.indexOf(':') === -1) {
|
|
||||||
matches.push({'key': 'n', '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("'") === 0 || value.indexOf('"') === 0) {
|
|
||||||
value = value.substring(1, value.length - 2);
|
|
||||||
}
|
|
||||||
if (key !== '' && value !== '' && _.any(['a', 'u', 'g'], function (item) {
|
|
||||||
return item === key;
|
|
||||||
})) {
|
|
||||||
matches.push({'key': key, 'value': value});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return _.filter($scope.info, function (item) {
|
return _.filter($scope.info, function (item) {
|
||||||
len = matches.length;
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
var match = matches[i];
|
var match = matches[i];
|
||||||
if (match.key === 'n') {
|
if (match.key === 'n') {
|
||||||
|
@ -61,7 +71,7 @@ var ProductListCtrl = ['$scope', '$location', '$routeParams', 'products', functi
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (match.key === 'a') {
|
} else if (match.key === 'a') {
|
||||||
if (item.IsActive === $scope.isTrue(match.value)) {
|
if (item.IsActive !== $scope.isTrue(match.value)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (match.key === 'u') {
|
} else if (match.key === 'u') {
|
||||||
|
|
|
@ -141,7 +141,9 @@ def show_list(request):
|
||||||
for item in list:
|
for item in list:
|
||||||
products.append({'Code': item.code, 'Name': item.name, 'Units': item.units, 'Price': item.price,
|
products.append({'Code': item.code, 'Name': item.name, 'Units': item.units, 'Price': item.price,
|
||||||
'ProductGroup': item.product_group.name, 'IsActive': item.is_active,
|
'ProductGroup': item.product_group.name, 'IsActive': item.is_active,
|
||||||
'IsFixture': item.is_fixture, 'Url': request.route_url('product_id', id=item.id)})
|
'Fraction': item.fraction, 'FractionUnits': item.fraction_units,
|
||||||
|
'ProductYield': item.product_yield, 'IsFixture': item.is_fixture,
|
||||||
|
'Url': request.route_url('product_id', id=item.id)})
|
||||||
return products
|
return products
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue