Skip to content

Commit 21b1f5c

Browse files
authored
Merge branch 'master' into OLMIS-8179-compact-inputs
2 parents be51f02 + 4dfb96f commit 21b1f5c

17 files changed

Lines changed: 664 additions & 13 deletions

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
==================
77

88
Improvements:
9+
* [OLMIS-8181](https://openlmis.atlassian.net/browse/OLMIS-8181): Disable doses input when net content is one.
10+
* [OLMIS-8118](https://openlmis.atlassian.net/browse/OLMIS-8118): Validate max value on positive integer inputs.
911
* [SELV3-748](https://openlmis.atlassian.net/browse/SELV3-748) Resolved cookie issue causing untranslated warning messages
1012
* [OLMIS-8192](https://openlmis.atlassian.net/browse/OLMIS-8192): Editable text inputs inside table cells now grow with their content.
1113

src/openlmis-adjustments/adjustments-modal.controller.js

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,13 @@
3131
AdjustmentsModalController.$inject = [
3232
'$filter', '$q', 'modalDeferred', 'title', 'message', 'isDisabled', 'adjustments',
3333
'reasons', 'summaries', 'preSave', 'preCancel', 'filterReasons', 'showInDoses', 'lineItem',
34-
'quantityUnitCalculateService'
34+
'quantityUnitCalculateService', 'alertService'
3535
];
3636

3737
function AdjustmentsModalController($filter, $q, modalDeferred, title, message, isDisabled,
3838
adjustments, reasons, summaries, preSave, preCancel,
39-
filterReasons, showInDoses, lineItem, quantityUnitCalculateService) {
39+
filterReasons, showInDoses, lineItem, quantityUnitCalculateService,
40+
alertService) {
4041

4142
var vm = this;
4243

@@ -45,6 +46,7 @@
4546
vm.removeAdjustment = removeAdjustment;
4647
vm.cancel = cancel;
4748
vm.save = save;
49+
vm.hasInvalidAdjustments = hasInvalidAdjustments;
4850

4951
/**
5052
* @ngdoc property
@@ -180,6 +182,11 @@
180182
* Adds adjustment to line item.
181183
*/
182184
function addAdjustment() {
185+
if (vm.newAdjustment && !hasValidQuantity(vm.newAdjustment)) {
186+
alertService.error('openlmisAdjustments.quantityGreaterThanZero');
187+
return $q.when();
188+
}
189+
183190
vm.adjustments.push(vm.newAdjustment);
184191

185192
vm.newAdjustment = undefined;
@@ -223,6 +230,11 @@
223230
* back to the modal without applying any changes;
224231
*/
225232
function save() {
233+
if (hasInvalidAdjustments()) {
234+
alertService.error('openlmisAdjustments.quantityGreaterThanZero');
235+
return;
236+
}
237+
226238
if (preSave) {
227239
preSave(vm.adjustments)
228240
.then(function() {
@@ -250,6 +262,22 @@
250262
modalDeferred.reject();
251263
}
252264
}
265+
266+
function hasInvalidAdjustments() {
267+
return (vm.adjustments || []).some(function(adjustment) {
268+
return !hasValidQuantity(adjustment);
269+
});
270+
}
271+
272+
function hasValidQuantity(adjustment) {
273+
return adjustment !== undefined
274+
&& adjustment !== null
275+
&& adjustment.quantity !== undefined
276+
&& adjustment.quantity !== null
277+
&& adjustment.quantity !== ''
278+
&& !isNaN(adjustment.quantity)
279+
&& Number(adjustment.quantity) > 0;
280+
}
253281
}
254282

255283
})();

src/openlmis-adjustments/adjustments-modal.controller.spec.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ describe('AdjustmentsModalController', function() {
2222
this.$q = $injector.get('$q');
2323
this.$rootScope = $injector.get('$rootScope');
2424
this.$controller = $injector.get('$controller');
25+
this.alertService = $injector.get('alertService');
2526
});
2627

2728
this.modalDeferred = this.$q.defer();
@@ -67,6 +68,7 @@ describe('AdjustmentsModalController', function() {
6768

6869
spyOn(this.modalDeferred, 'resolve');
6970
spyOn(this.modalDeferred, 'reject');
71+
spyOn(this.alertService, 'error');
7072

7173
this.initController = initController;
7274
});
@@ -191,6 +193,52 @@ describe('AdjustmentsModalController', function() {
191193
expect(this.filterReasons).toHaveBeenCalledWith(this.vm.adjustments);
192194
});
193195

196+
it('should not add adjustment and should show error when quantity is zero', function() {
197+
this.vm.newAdjustment = {
198+
reason: this.vm.reasons[0],
199+
quantity: 0
200+
};
201+
202+
this.vm.addAdjustment();
203+
204+
expect(this.vm.adjustments.length).toBe(2);
205+
expect(this.alertService.error)
206+
.toHaveBeenCalledWith('openlmisAdjustments.quantityGreaterThanZero');
207+
});
208+
209+
it('should not add adjustment and should show error when quantity is empty', function() {
210+
this.vm.newAdjustment = {
211+
reason: this.vm.reasons[0],
212+
quantity: ''
213+
};
214+
215+
this.vm.addAdjustment();
216+
217+
expect(this.vm.adjustments.length).toBe(2);
218+
expect(this.alertService.error)
219+
.toHaveBeenCalledWith('openlmisAdjustments.quantityGreaterThanZero');
220+
});
221+
222+
it('should not add adjustment and should show error when quantity is negative', function() {
223+
this.vm.newAdjustment = {
224+
reason: this.vm.reasons[0],
225+
quantity: -5
226+
};
227+
228+
this.vm.addAdjustment();
229+
230+
expect(this.vm.adjustments.length).toBe(2);
231+
expect(this.alertService.error)
232+
.toHaveBeenCalledWith('openlmisAdjustments.quantityGreaterThanZero');
233+
});
234+
235+
it('should not show error when quantity is greater than zero', function() {
236+
this.vm.addAdjustment();
237+
238+
expect(this.vm.adjustments.length).toBe(3);
239+
expect(this.alertService.error).not.toHaveBeenCalled();
240+
});
241+
194242
});
195243

196244
describe('removeAdjustment', function() {
@@ -297,6 +345,33 @@ describe('AdjustmentsModalController', function() {
297345
expect(this.modalDeferred.resolve).not.toHaveBeenCalled();
298346
});
299347

348+
it('should not resolve modalDeferred and should show error if any adjustment has invalid quantity',
349+
function() {
350+
this.adjustments = [{
351+
reason: this.reasons[0],
352+
quantity: 0
353+
}];
354+
355+
this.initController();
356+
this.vm.$onInit();
357+
358+
this.vm.save();
359+
360+
expect(this.modalDeferred.resolve).not.toHaveBeenCalled();
361+
expect(this.alertService.error)
362+
.toHaveBeenCalledWith('openlmisAdjustments.quantityGreaterThanZero');
363+
});
364+
365+
it('should not show error if all adjustments have valid quantities', function() {
366+
this.initController();
367+
this.vm.$onInit();
368+
369+
this.vm.save();
370+
371+
expect(this.alertService.error).not.toHaveBeenCalled();
372+
expect(this.modalDeferred.resolve).toHaveBeenCalledWith(this.vm.adjustments);
373+
});
374+
300375
});
301376

302377
describe('cancel', function() {

src/openlmis-adjustments/messages_en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@
1111
"openlmisAdjustments.total": "Total",
1212
"openlmisAdjustments.update": "Update",
1313
"openlmisAdjustments.actions": "Actions",
14-
"openlmisAdjustments.close": "Close"
14+
"openlmisAdjustments.close": "Close",
15+
"openlmisAdjustments.quantityGreaterThanZero": "Quantity must be greater than 0"
1516
}

src/openlmis-app-cache/openlmis-app-cache.controller.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@
6060
* Initialization method of the OpenlmisAppCacheController.
6161
*/
6262
function onInit() {
63-
appCache.addEventListener('updateready', setUpdateReady);
63+
if (appCache) {
64+
appCache.addEventListener('updateready', setUpdateReady);
65+
}
6466
vm.buildDate = OPENLMIS_BUILD_DATE;
6567
setUpdateReady();
6668
}
@@ -97,7 +99,7 @@
9799
}
98100

99101
function setUpdateReady() {
100-
vm.updateReady = appCache.status === appCache.UPDATEREADY;
102+
vm.updateReady = !!appCache && appCache.status === appCache.UPDATEREADY;
101103
}
102104

103105
}

src/openlmis-app-cache/openlmis-app-cache.controller.spec.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ describe('OpenlmisAppCacheController', function() {
2424
this.$rootScope = $injector.get('$rootScope');
2525
this.$controller = $injector.get('$controller');
2626
this.$q = $injector.get('$q');
27+
this.OPENLMIS_BUILD_DATE = $injector.get('OPENLMIS_BUILD_DATE');
2728
});
2829

2930
this.applicationCacheMock = jasmine.createSpyObj('applicationCache', [
@@ -146,4 +147,47 @@ describe('OpenlmisAppCacheController', function() {
146147

147148
});
148149

150+
// The deprecated window.applicationCache has been removed from modern browsers,
151+
// so $window.applicationCache can be undefined. The controller must not crash.
152+
describe('when applicationCache is not available', function() {
153+
154+
beforeEach(function() {
155+
this.vm = this.$controller('OpenlmisAppCacheController', {
156+
$window: {
157+
applicationCache: undefined,
158+
location: this.locationMock
159+
}
160+
});
161+
});
162+
163+
it('should not throw on init', function() {
164+
var vm = this.vm;
165+
166+
expect(function() {
167+
vm.$onInit();
168+
}).not.toThrow();
169+
});
170+
171+
it('should still set the build date', function() {
172+
this.vm.$onInit();
173+
174+
expect(this.vm.buildDate).toBe(this.OPENLMIS_BUILD_DATE);
175+
});
176+
177+
it('should set updateReady flag to false', function() {
178+
this.vm.$onInit();
179+
180+
expect(this.vm.updateReady).toBe(false);
181+
});
182+
183+
it('should do nothing when updateCache is called', function() {
184+
this.vm.$onInit();
185+
186+
this.vm.updateCache();
187+
188+
expect(this.confirmService.confirm).not.toHaveBeenCalled();
189+
});
190+
191+
});
192+
149193
});

src/openlmis-form/positive-integer.directive.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,26 @@
2323
* @name openlmis-form.directive:positiveInteger
2424
*
2525
* @description
26-
* Restricts the ngModel to only allow positive integers.
26+
* Restricts the ngModel to only allow positive integers. Values larger than the maximum safe
27+
* integer in JavaScript are rejected (the 'max' validity is set to false), because parseInt
28+
* would otherwise silently overflow and send a wrong value. When the java-integer attribute is
29+
* present the limit is lowered to the maximum Java Integer value.
2730
*
2831
* @example
2932
* Extend the input element to force it to only accept positive integers as values.
3033
* ```
3134
* <input ng-model="someModel" positive-integer>
3235
* ```
36+
* Add the java-integer attribute to additionally reject values exceeding the Java Integer range.
37+
* ```
38+
* <input ng-model="someModel" positive-integer java-integer>
39+
* ```
3340
*/
41+
var JAVA_INTEGER_MAX = Math.pow(2, 31) - 1;
42+
3443
angular
3544
.module('openlmis-form')
45+
.constant('JAVA_INTEGER_MAX', JAVA_INTEGER_MAX)
3646
.directive('positiveInteger', positiveInteger);
3747

3848
function positiveInteger() {
@@ -59,7 +69,14 @@
5969
modelCtrl.$render();
6070
}
6171

62-
return transformedInput ? parseInt(transformedInput) : null;
72+
var parsed = transformedInput ? parseInt(transformedInput) : null;
73+
74+
var maxValue = attrs.hasOwnProperty('javaInteger')
75+
? JAVA_INTEGER_MAX
76+
: Number.MAX_SAFE_INTEGER;
77+
modelCtrl.$setValidity('max', !parsed || parsed <= maxValue);
78+
79+
return parsed;
6380
});
6481
}
6582
}

0 commit comments

Comments
 (0)