Fix: Errors in the comparators in Tokenizer

Feature: Product list shows more information
This commit is contained in:
tanshu 2016-03-16 21:11:08 +05:30
parent 3df2146ba2
commit 1439befc46
6 changed files with 100 additions and 16 deletions

View File

@ -12,7 +12,7 @@
<link rel="stylesheet" type="text/css" media="screen" href="/css/bootstrap.min.css"/>
<!-- <link rel="stylesheet" type="text/css" media="screen" href="/css/bootstrap-theme.min.css"/> -->
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/angular_material/1.0.0/angular-material.min.css"/>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/table.css"/>
<link rel="stylesheet" type="text/css" media="screen" href="/css/chosen.min.css"/>
<link rel="stylesheet" type="text/css" media="screen" href="/css/loading-bar.min.css"/>

View File

@ -55,7 +55,6 @@
<md-option ng-repeat="pg in productGroups" value="{{pg.ProductGroupID}}">{{pg.Name}}</md-option>
</md-select>
</md-input-container>
</div>
<section layout="row" layout-sm="column" layout-align="center center">
<md-button class="md-raised md-primary" ng-click="save()">Save</md-button>

View File

@ -2,14 +2,37 @@
<div layout="row">
<md-input-container flex="grow">
<input type="text" ng-model="search" md-autofocus
placeholder="Search: n:Name, a:Active, u:Units, t:Type and e:true for extended properties">
placeholder="Search: n:Name, u:Units, s:Sold, p:Purchased, a:Active, t:Type and e:true for extended properties">
</md-input-container>
<md-input-container flex>
<md-button ng-href="/Product">Add <i
class="glyphicon glyphicon-plus"></i></md-button>
</md-input-container>
</div>
<div layout="row">
<md-input-container flex="20">
<label>Is Purchased?</label>
<md-select ng-model="isPurchased" ng-model-options="{ getterSetter: true }" placeholder="Is Purchased?">
<md-option value="null">All</md-option>
<md-option value="true">Yes</md-option>
<md-option value="false">No</md-option>
</md-select>
</md-input-container>
<md-input-container flex="20">
<label>Is Sold?</label>
<md-select ng-model="isSold" ng-model-options="{ getterSetter: true }" placeholder="Is Sold?">
<md-option value="null">All</md-option>
<md-option value="true">Yes</md-option>
<md-option value="false">No</md-option>
</md-select>
</md-input-container>
<md-input-container flex="30">
<label>Product Group</label>
<md-select ng-model="productGroup" ng-model-options="{ getterSetter: true }" placeholder="Product Group">
<md-option ng-repeat="pg in product_groups" value="{{pg}}">{{pg}}</md-option>
</md-select>
</md-input-container>
</div>
<table class="table table-condensed table-bordered table-striped" keypress="shortcuts">
<thead>
<tr>
@ -18,7 +41,7 @@
<th class="text-right">Price</th>
<th ng-if="showExtended" class="text-right">Yield</th>
<th>Type</th>
<th>Is Active?</th>
<th>Details</th>
</tr>
</thead>
<tbody>
@ -27,10 +50,31 @@
<td class="text-right">{{item.Code}}</td>
<td><a href="{{item.Url}}">{{item.Name}} ({{showExtended ? item.Fraction + ' ' + item.FractionUnits + ' = 1 ' :
''}}{{item.Units}})</a></td>
<td class="text-right">{{item.Price | currency}}</td>
<td class="text-right">{{item.CostPrice | currency}}</td>
<td ng-if="showExtended" class="text-right">{{item.ProductYield * 100 | number:2}}%</td>
<td>{{item.ProductGroup}}</td>
<td>{{item.IsActive}}</td>
<td>
<div layout="row">
<div flex>
<md-icon>
{{ item.IsPurchased ? "shopping_cart" : "remove_shopping_cart" }}
</md-icon>
<b>{{ item.IsPurchased ? "Purchased" : "Made" }}</b>
</div>
<div flex>
<md-icon>
{{ item.IsSold ? "restaurant_menu" : "import_contacts" }}
</md-icon>
<b>{{ item.IsSold ? "Sold" : "Used" }}</b>
</div>
<div flex>
<md-icon>
{{ item.IsActive ? "visibility" : "visibility_off" }}
</md-icon>
<b>{{ item.IsActive ? "Active" : "Deactivated" }}</b>
</div>
</div>
</td>
</tr>
</tbody>
</table>

View File

@ -264,9 +264,9 @@ overlordService.factory('Tokenizer', ['$filter', function ($filter) {
comparators = {
'text': function (obj, text) {
if (text.indexOf('!') === 0) {
return obj.toLowerCase().indexOf(text.substr(1)) <= -1;
return !obj.toLowerCase().includes(text.substr(1).toLowerCase());
} else {
return obj.toLowerCase().indexOf(text) > -1;
return obj.toLowerCase().includes(text.toLowerCase());
}
},
'date': function (obj, text) {
@ -333,7 +333,7 @@ overlordService.factory('Tokenizer', ['$filter', function ($filter) {
key = key.substring(1, key.length - 1).trim();
}
if (value.indexOf("'") !== -1 || value.indexOf('"') !== -1) {
value = key.substring(1, value.length - 1).trim();
value = value.substring(1, value.length - 1).trim();
}
if (value !== '') {
accumulator.push({Key: key, Value: value});

View File

@ -4,6 +4,45 @@ var ProductListController = ['$scope', '$location', '$routeParams', 'Tokenizer',
$scope.search = $routeParams.q || '';
$scope.showExtended = false;
$scope.info = products;
$scope.product_groups = _.reduce(products, function (acculumator, item) {
if (!acculumator.includes(item.ProductGroup)){
acculumator.push(item.ProductGroup);
}
return acculumator;
},[]).sort();
$scope.isPurchased = function (isPurchased) {
if (arguments.length === 0) {
return $scope._isPurchased;
}
$scope._isPurchased = isPurchased;
var re = /(('[p]'|"[p]"|[p]+)\s*:\s*('[^']+'|"[^"]+"|[^\s]+))/gi,
matches = $scope.search.match(re),
st = isPurchased === 'null' ? '' : 'p:' + isPurchased;
$scope.search = (matches === null) ? $scope.search.trim() + ' ' + st : $scope.search.replace(re, st);
};
$scope.isSold = function (isSold) {
if (arguments.length === 0) {
return $scope._isSold;
}
$scope._isSold = isSold;
var re = /(('[s]'|"[s]"|[s]+)\s*:\s*('[^']+'|"[^"]+"|[^\s]+))/gi,
matches = $scope.search.match(re),
st = isSold === 'null' ? '' : 's:' + isSold;
$scope.search = (matches === null) ? $scope.search.trim() + ' ' + st : $scope.search.replace(re, st);
};
$scope.productGroup = function (productGroup) {
if (arguments.length === 0) {
return $scope._productGroup;
}
$scope._productGroup = productGroup;
var re = /(('[t]'|"[t]"|[t]+)\s*:\s*('[^']+'|"[^"]+"|[^\s]+))/gi,
matches = $scope.search.match(re),
st = 't:"' + productGroup + '"';
$scope.search = (matches === null) ? $scope.search.trim() + ' ' + st : $scope.search.replace(re, st);
};
$scope.$watch('search', function (value) {
$scope.filterProducts(value);
@ -16,8 +55,10 @@ var ProductListController = ['$scope', '$location', '$routeParams', 'Tokenizer',
$scope.searchInfo = {
comparator: {
'n': {'Col': 'Name', 'Comparator': 'text'},
'a': {'Col': 'IsActive', 'Comparator': 'boolean'},
'u': {'Col': 'Units', 'Comparator': 'text'},
'a': {'Col': 'IsActive', 'Comparator': 'boolean'},
's': {'Col': 'IsSold', 'Comparator': 'boolean'},
'p': {'Col': 'IsPurchased', 'Comparator': 'boolean'},
't': {'Col': 'ProductGroup', 'Comparator': 'text'},
'y': {'Col': 'ProductYield', 'Comparator': 'numeric'}
},

View File

@ -155,11 +155,11 @@ def show_list(request):
Product.name).all()
products = []
for item in list:
products.append({'Code': item.code, 'Name': item.name, 'Units': item.units, 'Price': item.price,
'ProductGroup': item.product_group.name, 'IsActive': item.is_active,
'Fraction': item.fraction, 'FractionUnits': item.fraction_units,
'ProductYield': item.product_yield, 'IsFixture': item.is_fixture,
'Url': request.route_url('product_id', id=item.id)})
products.append({'Code': item.code, 'Name': item.name, 'Units': item.units, 'CostPrice': item.price,
'SalePrice': item.sale_price, 'ProductGroup': item.product_group.name,
'IsActive': item.is_active, 'Fraction': item.fraction, 'FractionUnits': item.fraction_units,
'IsPurchased': item.is_purchased, 'IsSold': item.is_sold, 'ProductYield': item.product_yield,
'IsFixture': item.is_fixture, 'Url': request.route_url('product_id', id=item.id)})
return products