Skip to content

Commit

Permalink
feat(filters): improve filter ui rendering
Browse files Browse the repository at this point in the history
This commit improves the filters ui again by introducing the following
upgrades:
 1. The server uses `moment` to parse dates in the date filters.  The
 code on the server for rendering the filters is very similar to the
 clientside codebase, which is unavoidable.  There might be an
 optimisation down the road to reduce this replication, but I think this
 is acceptable for now.

 2. The filters are now passed into the filter form and preset there.
 That way, when you go to filter a second time, all the data is
 preserved.

 3. A weird bug with caching filters was fixed.  The detailed flag no
 longer shows up as a potential filter, and refreshing the page after
 printing no longer breaks the browser.

 4. The date rendering has been improved in the handlebar's date helper
 function.  If an invalid date occurs, it will simply render the empty
 string.

 5. The `$uibModal` handler now implements the behavior described in
 #506.

Closes #492.  Closes #336.
  • Loading branch information
jniles committed Jun 21, 2016
1 parent 3f7bc03 commit 45f2f44
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 62 deletions.
44 changes: 25 additions & 19 deletions client/src/js/services/PatientService.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,17 @@ PatientService.$inject = [ '$http', 'util', 'SessionService', '$uibModal', 'Docu
/**
* @module PatientService
*
* This service is reponsible for providing an interface between angular
* This service is responsible for providing an interface between angular
* module controllers and the server /patients API.
*
* @example
* Controller.$inject = ['PatientService'];
*
* var Patients = PatientService;
*
* // returns patient details
* Patients.read(uuid)...
*
* // creates a patient
* Patients.create(medicalDetails, financeDetails)...
* function Controller(Patients) {
* // returns patient details
* Patients.read(uuid).then(callback);
*
* // creates a patient
* Patients.create(medicalDetails, financeDetails).then(callback);
* }
*/
function PatientService($http, util, Session, $uibModal, Documents, Visits) {
var service = this;
Expand Down Expand Up @@ -133,7 +130,7 @@ function PatientService($http, util, Session, $uibModal, Documents, Visits) {
* paramSerializer
*/
function search(options) {
options = options || {};
options = angular.copy(options || {});

var target = baseUrl.concat('search');

Expand Down Expand Up @@ -200,22 +197,21 @@ function PatientService($http, util, Session, $uibModal, Documents, Visits) {
}


/*
/**
* This function prepares the headers patient properties which were filtered,
* Special treatment occurs when processing data related to the date
* @todo - this might be better in it's own service
*/
function formatFilterParameters(params) {

var columns = [
{ field: 'name', displayName: 'FORM.LABELS.NAME' },
{ field: 'sex', displayName: 'FORM.LABELS.GENDER' },
{ field: 'hospital_no', displayName: 'FORM.LABELS.HOSPITAL_NO' },
{ field: 'reference', displayName: 'FORM.LABELS.REFERENCE' },
{ field: 'dateBirthFrom', displayName: 'FORM.LABELS.DOB', comparitor: '<', ngFilter:'date' },
{ field: 'dateBirthTo', displayName: 'FORM.LABELS.DOB', comparitor: '>', ngFilter:'date' },
{ field: 'dateRegistrationFrom', displayName: 'FORM.LABELS.DATE_REGISTRATION', comparitor: '<', ngFilter:'date' },
{ field: 'dateRegistrationTo', displayName: 'FORM.LABELS.DATE_REGISTRATION', comparitor: '>', ngFilter:'date' },
{ field: 'dateBirthFrom', displayName: 'FORM.LABELS.DOB', comparitor: '>', ngFilter:'date' },
{ field: 'dateBirthTo', displayName: 'FORM.LABELS.DOB', comparitor: '<', ngFilter:'date' },
{ field: 'dateRegistrationFrom', displayName: 'FORM.LABELS.DATE_REGISTRATION', comparitor: '>', ngFilter:'date' },
{ field: 'dateRegistrationTo', displayName: 'FORM.LABELS.DATE_REGISTRATION', comparitor: '<', ngFilter:'date' },
];

// returns columns from filters
Expand All @@ -231,13 +227,23 @@ function PatientService($http, util, Session, $uibModal, Documents, Visits) {
});
}

function openSearchModal() {
/**
* @method openSearchModal
*
* @param {Object} params - an object of filter parameters to be passed to
* the modal.
* @returns {Promise} modalInstance
*/
function openSearchModal(params) {
return $uibModal.open({
templateUrl: 'partials/patients/registry/search.modal.html',
size: 'md',
keyboard: false,
animation: true,
controller: 'PatientRegistryModalController as ModalCtrl'
controller: 'PatientRegistryModalController as ModalCtrl',
resolve : {
params : function paramsProvider() { return params; }
}
}).result;
}

Expand Down
4 changes: 1 addition & 3 deletions client/src/js/services/receipts/ReceiptService.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function ReceiptService($http, util) {
*
* @param {String} uuid Target invoice UUID to report on
* @param {Object} options Configuration options for the server generated
* report, this includes things like render target.
* report, this includes things like renderer target.
* @return {Promise} Eventually returns report object from server
*/
function invoice(uuid, options) {
Expand Down Expand Up @@ -63,8 +63,6 @@ function ReceiptService($http, util) {
responseType = 'arraybuffer';
}

delete options.render;

return $http.get(route, {params : options, responseType : responseType})
.then(util.unwrapHttpResponse);
}
Expand Down
7 changes: 6 additions & 1 deletion client/src/partials/patients/registry/registry.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@
>
</bh-filters-applied>

<a ng-click="PatientRegistryCtrl.clearFilters()" ng-show="PatientRegistryCtrl.filtersFmt.length > 0" href class="text-danger" data-method="clear">
<a
href
ng-click="PatientRegistryCtrl.clearFilters()"
ng-show="PatientRegistryCtrl.filtersFmt.length > 0"
class="text-danger"
data-method="clear">
<i class="fa fa-ban text-danger"></i>
{{ "FORM.INFOS.CLEAR_FILTERS" | translate }}
</a>
Expand Down
17 changes: 9 additions & 8 deletions client/src/partials/patients/registry/registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,8 @@ function PatientRegistryController(Patients, Notify, moment, Receipt, AppCache,

// error handler
function handler(error) {
if (error) {
vm.hasError = true;
Notify.handleError(error);
}
vm.hasError = true;
Notify.handleError(error);
}

// this uses function loads patients from the database with search parameters
Expand All @@ -78,9 +76,8 @@ function PatientRegistryController(Patients, Notify, moment, Receipt, AppCache,
// hook the returned patients up to the grid.
request.then(function (patients) {

// this will improve with @dedrickenc's pull requst
patients.forEach(function (patient) {
patient.patientAge = util.getMomentAge(patient.dob);
patient.patientAge = util.getMomentAge(patient.dob, 'years');
});

// put data in the grid
Expand All @@ -94,8 +91,12 @@ function PatientRegistryController(Patients, Notify, moment, Receipt, AppCache,

// search and filter data in Patient Registry
function search() {
Patients.openSearchModal()
Patients.openSearchModal(vm.filters)
.then(function (parameters) {

// no parameters means the modal was dismissed.
if (!parameters) { return; }

cacheFilters(parameters);
return load(vm.filters);
});
Expand All @@ -122,7 +123,7 @@ function PatientRegistryController(Patients, Notify, moment, Receipt, AppCache,

// open a print modal to print all patient registrations to date
function print() {
var options = vm.filters || {};
var options = angular.copy(vm.filters || {});

// @todo(jniles): Make reports and receipts use the same rendering modal
Receipt.patientRegistrations(options);
Expand Down
19 changes: 12 additions & 7 deletions client/src/partials/patients/registry/search.modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,35 @@ angular.module('bhima.controllers')
.controller('PatientRegistryModalController', PatientRegistryModalController);

PatientRegistryModalController.$inject = [
'$uibModalInstance', 'PatientService', 'DateService'
'$uibModalInstance', 'PatientService', 'DateService', 'params'
];

/**
* @class PatientRegistryModalController
*
* @description
* This controller is responsible for setting up the filters for the patient
* search functionality on the patient registry page.
* search functionality on the patient registry page. Filters that are already
* applied to the grid can be passed in via the params inject.
*/
function PatientRegistryModalController(ModalInstance, Patients, Dates) {
function PatientRegistryModalController(ModalInstance, Patients, Dates, params) {
var vm = this;

// bind period labels from the service
vm.periods = Dates.period();
vm.today = new Date();

// this will hold the parameters
vm.params = {};
// bind filters if they have already been applied. Otherwise, default to an
// empty object.
vm.params = params || {};

// bind methods
vm.submit = submit;
vm.cancel = cancel;
vm.clear = clear;
vm.setDateRange = setDateRange;

// returns the parameters to the parent controller
function submit(form) {
if (form.$invalid) { return; }

Expand All @@ -43,7 +46,8 @@ function PatientRegistryModalController(ModalInstance, Patients, Dates) {
return ModalInstance.close(parameters);
}

// clears search parameters
// clears search parameters. Custom logic if a date is used so that we can
// clear two properties.
function clear(value) {
if (value === 'registration') {
delete vm.params.dateRegistrationFrom;
Expand Down Expand Up @@ -87,7 +91,8 @@ function PatientRegistryModalController(ModalInstance, Patients, Dates) {
}
}

// dismiss the modal
function cancel() {
ModalInstance.dismiss();
ModalInstance.close();
}
}
19 changes: 13 additions & 6 deletions client/test/e2e/patient/registry.search.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ function PatientRegistrySearch() {

expectNumberOfGridRows(1);
expectNumberOfFilters(1);
FU.buttons.clear();
});

// demonstrates additive filters
Expand All @@ -70,6 +71,7 @@ function PatientRegistrySearch() {

expectNumberOfGridRows(2);
expectNumberOfFilters(2);
FU.buttons.clear();
});

// demonstrates that additive + time-delimited filtering works
Expand All @@ -81,6 +83,7 @@ function PatientRegistrySearch() {

expectNumberOfGridRows(1);
expectNumberOfFilters(3);
FU.buttons.clear();
});

// demonstrates that sex + time-delimited filtering works
Expand All @@ -92,6 +95,7 @@ function PatientRegistrySearch() {

expectNumberOfGridRows(1);
expectNumberOfFilters(3);
FU.buttons.clear();
});

// changes every single date input manually.
Expand All @@ -107,6 +111,7 @@ function PatientRegistrySearch() {

expectNumberOfGridRows(0);
expectNumberOfFilters(4);
FU.buttons.clear();
});

// combines dates with manual date manipulation
Expand All @@ -119,8 +124,10 @@ function PatientRegistrySearch() {
element(by.id('male')).click();

FU.buttons.submit();

expectNumberOfGridRows(2);
expectNumberOfFilters(3);
FU.buttons.clear();
});

// clears filters to assert that the "error state" bug does not occur when the
Expand All @@ -135,31 +142,31 @@ function PatientRegistrySearch() {
expectNumberOfFilters(3);

// click the "clear filters" button
$('[data-method="clear"]').click();
FU.buttons.clear();

// the filter bar shouldn't exist
expectNumberOfGridRows(defaultVisibleRowNumber);
expectNumberOfFilters(0);
});

it('should remember the cached filters', () => {

FU.buttons.search();

// Add all the filters (7 in total)
$('[data-date-registration]').$('[data-date-range="today"]').click();
// Add all the filters (4 in total)
$('[data-date-dob]').$('[data-date-range="year"]').click();
element(by.id('male')).click();
FU.input('ModalCtrl.params.name', 'Some Non-Existant Patient');
FU.input('ModalCtrl.params.reference', 'TPA#');

FU.buttons.submit();

expectNumberOfGridRows(0);
expectNumberOfFilters(7);
expectNumberOfFilters(4);

browser.refresh();

expectNumberOfGridRows(0);
expectNumberOfFilters(7);
expectNumberOfFilters(4);
FU.buttons.clear();
});
}
3 changes: 2 additions & 1 deletion client/test/e2e/shared/FormUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ helpers.configure(chai);
// These buttons depend on custom data tags to indicate actions. This seems
// cleaner than using a whole bunch of ids which may potentially collide.
// However, this decision can be reviewed
var buttons = {
const buttons = {
create: function create() { return $('[data-method="create"]').click(); },
search: function search() { return $('[data-method="search"]').click(); },
submit: function submit() { return $('[data-method="submit"]').click(); },
cancel: function cancel() { return $('[data-method="cancel"]').click(); },
clear: function clear() { return $('[data-method="clear"]').click(); },
back: function back() { return $('[data-method="back"]').click(); },
delete: function delet() { return $('[data-method="delete"]').click(); }
};
Expand Down
9 changes: 8 additions & 1 deletion server/controllers/medical/reports/registrations.handlebars
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,14 @@
<p class="pills">
{{#each metadata.filters}}
<span class="label label-primary text-capitalize">
<i class="fa fa-filter"></i> {{@key}}: {{this}}
{{! this madness is to make sure dates are properly formatted }}
<i class="fa fa-filter"></i> {{translate this.displayName}}:

{{#if this.comparitor}} {{this.comparitor}} {{/if}}

{{#if this.isDate}} {{date this.value}}
{{else}} {{this.value}} {{/if}}

</span>
{{/each}}
</p>
Expand Down

0 comments on commit 45f2f44

Please sign in to comment.