Skip to content

Commit

Permalink
BS-258 | SNOMED Changes (#768)
Browse files Browse the repository at this point in the history
* BS-160 | Patrick | Filter and display only current medication alert (#662)

* BS-160 | Patrick | Close alerts when medication input is cleared (#670)

* BS 216 | BS-Drug Drug - Enhance FHIR CDSS Service based on Standard Format(Only Salt scope) (#673)

* BS-216 | Mani, Siva | updated filtering cdss alert logic

* BS-216 | Mani, Siva | fixed ts lint

* BS-207 | Placement of previous alerts near Drugs (#683)

* BS-207 | Patrick | add CDSS alert icons and tooltips for previous drug alerts

* BS-207 | Patrick | Fix tooltip placement

* BS-207 | Patrick | add cdss alert details and link

* BS-207 | Patrick | make CDSS alert icon a button

* BS-207 | Patrick | fix alert icon button size

* BS-207 | Patrick | Refactor previous alert filtering logic

* BS-207 | Patrick | Refactor new drug order alert filtering logic

* BS-207 | Patrick | remove font size from global icon class

* BS-207 | Patrick | Allow multiple cdss alerts in one tooltip

* BS-207 | Patrick | move tooltip trigger to button

* BS-207 | Patrick | Fix tooltip padding

* BS-207 | Patrick | Add directive for CDSS alerts

* BS-207 | Patrick | Add watchers for the alerts and treatment changes

* BS-207 | Patrick | Add translations for "Dismissed"

* BS-207 | Patrick | Add unit tests

* BS-207 | Patrick | remove translations for other languages

* BS-208 | Placement of Alert near Diagnosis (#687)

* BS-208 | Patrick | Add alerts for past and saved diagnoses

* BS-208 | Patrick | Update system information in FHIR bundle payload

* BS-208 | Patrick | update drug uuid when getting drug concept system

* BS-208 | Patrick | Refactor alert filtering

* BS-208 | Patrick | fix circular dependency bug and styling

* BS-208 | Patrick | Refactor to include unsaved medication

* BS-208 | Patrick | refactor bundle generation for draft drugs

* BS-208 | Patrick | create CDSS service

* BS-208 | Patrick | Remove unused cdss methods for diagnosis and treatment

* BS-208 | Patrick | Add Unit tests

* BS 247 - FHIR Export Admin UI (#757)

* BS-247 | Vijay,Siva | Admin UI

* BS-247 | Vijay,Siva | Admin UI Unit Test

* BS-247 | Vijay,Mani,Siva | restore missing code

* BS-247 | Vijay,Siva | restore missing code

* BS-247 | Vijay | add mising file

* BS-247 | vijay | add username and fix date format

* BS-247 | vijay | i18n

* BS-247 | vijay | cleanup

* BS-58: Trigger and show CDSS Active alert alert at the diagnosis/conditions and Medications tab (#728)

* BS-58 | Patrick | Add active and dismissed CDSS alert row form medications tab

* BS-58 | Patrick | trigger cdss also when updating medication

* BS-58 | Patrick | Fix cdss alert  audit

* BS-58 | Patrick | Fix alerts status update on diagnosis tab

* BS-58 | Patrick | Remove close button from diagnosis alert

* BS-58 | Patrick | align source link and watcher for new medication alerts

* BS-270 Added a  tooltip to procedures buttons (#723)

* BS-270 | Patrick | Add tooltip to procedures buttons

* BS-270 | Patrick | Show tooltip only if text overflows

* BS-270 | Patrick | fix formatting issues

* BS-270 | Vijay, Mani | remove timeout discrepancy

* BS-270 | Vijay, Mani | resolve timeout discrepancy

* BS-270 | Patrick | Add comment for tooltip positioning

---------

Co-authored-by: vijayanandtwks <vijayanand.s@thoughtworks.com>

* BS-282 | Adding Drug Reference Maps to Order set member (#758)

* BS-281 | CDSS Observations for all the interactions (#761)

* BS-281 | Patrick | fix diagnosis alert message layout

* BS=281 | Patrick | Show alerts on conditions change

* BS-281 | Patrick | Fix cdss popover button padding for conditions

* BS-281 | Patrick | Update cdss alerts filter to keep previous alert statuses

* BS-281 | patrick | Get alerts on drug refills

* BS-281 | Patrick | Add high dosage prefix for high dosage alerts

* BS-281 | Patrick | Fix medication duration error

* BS-281 | Patrick | Show alerts on dosage recalculation and activated condition status

* BS-281 | Patrick | Label saved medications and condition alerts as dismissed

* BS-281 | Patrick | Update diagnoses alerts if medication is removed

* BS-281 | Patrick | Change diagnosis alert link color to black

* BS-281 | Patrick | Align dismissed condition alert icon

* BS-281 | Patrick | Fix alert expand toggle in medications tab

* BS-281 | Patrick | Fix to Avoid calling CDSS methods if CDSS is disabled

* BS-281 | Patrick | Remove alerts from inactive diagnosis rows

* BS-283 | BS-285 | Mani | fixed issue when removal of last draft medications/conditions by adding patient resource to get patient id (#763)

* BS-283 | BS-285 | Mani | fixed issue when removal of last draft medications/conditions by adding patient resource to get patient id

* BS-283 | BS-285 | Mani | moved patient resource creation inside the guard condition

* BS-14 | Trigger CDSS on the Drug Order Sets (#765)

* BS-14 | Patrick | Add CDSS alerts for drug order sets

* BS-14 | Patrick | Fix button group styling

* BS281 | CDSS Observations for all the interactions (#766)

* BS-281 | Patrick | Fix closing alert issue

* BS-281 | Patrick | Clear alerts if diagnosis is cleared

* BS-281 | Patrick | Remove alerts for cleared conditions

* Adding missing Keys

---------

Co-authored-by: Patrick Nyatindo <nyatindopatrick@gmail.com>
Co-authored-by: manimaarans <110804183+manimaarans@users.noreply.github.com>
Co-authored-by: vijayanandtwks <vijayanand.s@thoughtworks.com>
  • Loading branch information
4 people authored Nov 3, 2023
1 parent 7e3022a commit 31ddb63
Show file tree
Hide file tree
Showing 50 changed files with 2,763 additions and 521 deletions.
7 changes: 7 additions & 0 deletions ui/app/admin/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ angular.module('admin')
data: {
backLinks: [{label: "Home", state: "admin.dashboard", icon: "fa-home"}]
}
}).state('admin.fhirExport', {
url: '/fhirExport',
templateUrl: 'views/fhirExport.html',
controller: 'FHIRExportController',
data: {
backLinks: [{label: "Home", state: "admin.dashboard", icon: "fa-home"}]
}
});
$httpProvider.defaults.headers.common['Disable-WWW-Authenticate'] = true;
$bahmniTranslateProvider.init({app: 'admin', shouldMerge: true});
Expand Down
101 changes: 101 additions & 0 deletions ui/app/admin/controllers/fhirExportController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
'use strict';

angular.module('bahmni.admin')
.controller('FHIRExportController', ['$rootScope', '$scope', '$q', '$http', '$translate', 'messagingService', 'fhirExportService', function ($rootScope, $scope, $q, $http, $translate, messagingService, fhirExportService) {
var DateUtil = Bahmni.Common.Util.DateUtil;

var convertToLocalDate = function (date) {
var localDate = DateUtil.parseLongDateToServerFormat(date);
return DateUtil.getDateTimeInSpecifiedFormat(localDate, 'MMMM Do, YYYY [at] h:mm:ss A');
};

var subtractDaysFromToday = function (minusDays) {
const currentDate = new Date();
currentDate.setDate(currentDate.getDate() - minusDays);
return currentDate;
};

$scope.startDate = subtractDaysFromToday(30);
$scope.endDate = subtractDaysFromToday(0);

$scope.anonymise = true;

var isLoggedInUserPrivileged = function (expectedPrivileges) {
var currentPrivileges = _.map($rootScope.currentUser.privileges, function (privilege) {
return privilege.name;
});
var hasPrivilege = expectedPrivileges.some(function (privilege) {
return currentPrivileges.indexOf(privilege) !== -1;
});
return hasPrivilege;
};

var hasInsufficientPrivilegeForPlainExport = function () {
var plainExportPrivileges = [Bahmni.Common.Constants.plainFhirExportPrivilege];
var hasPlainExportPrivilege = isLoggedInUserPrivileged(plainExportPrivileges);
return !hasPlainExportPrivilege;
};
$scope.isCheckboxDisabled = hasInsufficientPrivilegeForPlainExport();

var isUserPrivilegedForFhirExport = function () {
var defaultExportPrivileges = [Bahmni.Common.Constants.fhirExportPrivilege, Bahmni.Common.Constants.plainFhirExportPrivilege];
return isLoggedInUserPrivileged(defaultExportPrivileges);
};
$scope.hasExportPrivileges = isUserPrivilegedForFhirExport();

$scope.loadFhirTasksForPrivilegedUsers = function () {
var deferred = $q.defer();
$scope.tasks = [];
if (isUserPrivilegedForFhirExport()) {
fhirExportService.loadFhirTasks().then(function (response) {
if (response.data && response.data.entry) {
response.data.entry.map(function (task) {
task.resource.authoredOn = convertToLocalDate(task.resource.authoredOn);
return task;
});
$scope.tasks = response.data.entry;
deferred.resolve();
}
}).catch(function (error) {
deferred.reject(error);
});
}
return deferred.promise;
};

$scope.loadFhirTasksForPrivilegedUsers();

$scope.exportFhirData = function () {
var deferred = $q.defer();
var startDate = DateUtil.getDateWithoutTime($scope.startDate);
var endDate = DateUtil.getDateWithoutTime($scope.endDate);
var anonymise = $scope.anonymise;
var username = $rootScope.currentUser.username;

fhirExportService.export(username, startDate, endDate, anonymise).success(function () {
fhirExportService.submitAudit(username, startDate, endDate, anonymise).success(function () {
messagingService.showMessage("info", $translate.instant("EXPORT_PATIENT_REQUEST_SUBMITTED"));
$scope.loadFhirTasksForPrivilegedUsers();
deferred.resolve();
});
}).catch(function (error) {
messagingService.showMessage("error", $translate.instant("EXPORT_PATIENT_REQUEST_SUBMIT_ERROR"));
console.error("FHIR Export request failed");
deferred.reject(error);
});
return deferred.promise;
};

$scope.extractAttribute = function (array, searchValue, attributeToExtract) {
var foundElement = array && array.find(function (inputElement) { return inputElement.type.text === searchValue; });
if (foundElement && foundElement.hasOwnProperty(attributeToExtract)) {
return foundElement[attributeToExtract];
}
return null;
};

$scope.extractBoolean = function (array, searchValue, attributeToExtract) {
var booleanStr = $scope.extractAttribute(array, searchValue, attributeToExtract);
return booleanStr && booleanStr.toLowerCase() === "true";
};
}]);
3 changes: 2 additions & 1 deletion ui/app/admin/controllers/orderTemplateController.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
'drug': {
'name': drug.name,
'uuid': drug.uuid,
'form': drug.dosageForm.display
'form': drug.dosageForm.display,
'drugReferenceMaps': drug.drugReferenceMaps || []
},
'value': drug.name
};
Expand Down
2 changes: 2 additions & 0 deletions ui/app/admin/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,14 @@
<script src="controllers/csvUploadController.js"></script>
<script src="controllers/csvExportController.js"></script>
<script src="controllers/auditLogController.js"></script>
<script src="controllers/fhirExportController.js"></script>
<script src="controllers/orderSetDashboardController.js"></script>
<script src="controllers/orderSetController.js"></script>
<script src="controllers/orderTemplateController.js"></script>
<script src="controllers/adminDashboardController.js"></script>
<script src="services/adminImportService.js"></script>
<script src="services/adminOrderSetService.js"></script>
<script src="services/fhirExportService.js"></script>

<script src="../common/orders/init.js"></script>
<script src="../common/orders/services/orderTypeService.js"></script>
Expand Down
48 changes: 48 additions & 0 deletions ui/app/admin/services/fhirExportService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
'use strict';

angular.module('bahmni.admin')
.service('fhirExportService', ['$http', '$translate', 'messagingService', function ($http, $translate, messagingService) {
var DateUtil = Bahmni.Common.Util.DateUtil;
var convertToLocalDate = function (date) {
var localDate = DateUtil.parseLongDateToServerFormat(date);
return DateUtil.getDateTimeInSpecifiedFormat(localDate, 'MMMM Do, YYYY [at] h:mm:ss A');
};

this.loadFhirTasks = function () {
const params = {
"_sort:desc": "_lastUpdated",
_count: 50
};
return $http.get(Bahmni.Common.Constants.fhirTasks, {params: params});
};

this.submitAudit = function (username, startDate, endDate, anonymise) {
var eventType = "PATIENT_DATA_BULK_EXPORT";
var exportMode = anonymise ? "Anonymized" : "Non-Anonymized";
var message = "User " + username + " performed a bulk patient data export for: Start Date " + convertToLocalDate(startDate) + " and End Date " + convertToLocalDate(endDate) + " in " + exportMode + " mode";
var module = "Export";
var auditData = {
username: username,
eventType: eventType,
message: message,
module: module
};
return $http.post(Bahmni.Common.Constants.auditLogUrl, auditData, {
withCredentials: true
});
};

this.export = function (username, startDate, endDate, anonymise) {
var url = Bahmni.Common.Constants.fhirExportUrl + "?anonymise=" + anonymise;
if (startDate) {
url = url + "&startDate=" + startDate;
}
if (endDate) {
url = url + "&endDate=" + endDate;
}
return $http.post(url, {
withCredentials: true,
headers: {"Accept": "application/json", "Content-Type": "application/json"}
});
};
}]);
65 changes: 65 additions & 0 deletions ui/app/admin/views/fhirExport.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<div>
<div class="note-warning" ng-show="!hasExportPrivileges">
<p style="color: red;">{{ 'INSUFFICIENT_PRIVILEGE_TO_EXPORT'|translate }}</p>
</div>
<div class="note-warning" ng-show="hasExportPrivileges">
{{ 'EXPORT_PATIENT_DATA_WARNING'|translate }}
</div>
<div class="audit-log-filter">
<header>
<p>{{ 'PATIENT_DATA_BULK_FHIR_EXPORT_LABEL'|translate }}</p>
</header>
<article id="startFrom">
<form ng-submit="exportFhirData()">
<p>
<label for="startFrom">{{ 'FHIR_EXPORT_START_DATE_LABEL'|translate }} </label>
<input id="startDate" type="date" ng-model="startDate" max="{{::maxDate}}">
</p>
<p>
<label for="endDate">{{ 'FHIR_EXPORT_END_DATE_LABEL'|translate }} </label>
<input id="endDate" type="date" ng-model="endDate" max="{{::maxDate}}">
</p>
<P>
<div>
<input type="checkbox" id="anonymise" name="anonymise" ng-disabled="isCheckboxDisabled" ng-model="anonymise"/>
<label for="anonymise">Anonymise</label>
</div>
</P>
<button class="button" type="submit" ng-disabled="!hasExportPrivileges"> <aria-hidden="true"></i>
{{ 'FHIR_EXPORT_BUTTON_LABEL'|translate }}
</button>
</form>
</article>
</div>
<section class="block section-grid orderSet-dashboard-container">
<div class="clearfix section-title-wrapper">
<h2 class="section-title fl">{{ 'FHIR_EXPORT_TABLE_HEADER_LABEL'|translate }}</h2>
<button class="fr small-btn grid-row-element orderSet-Create" ng-disabled="!hasExportPrivileges" ng-click="loadFhirTasksForPrivilegedUsers()"> Refresh</button>
</div>
<table id="auditLogTable">
<thead>
<tr>
<th>{{ 'EXPORT_USER_NAME'|translate }}</th>
<th>{{ 'EXPORT_TRIGGERED_DATE'|translate }}</th>
<th>{{ 'EXPORT_START_DATE'|translate }}</th>
<th>{{ 'EXPORT_END_DATE'|translate }}</th>
<th>{{ 'EXPORT_ANONYMISED'|translate }}</th>
<th>{{ 'EXPORT_TASK_STATUS'|translate }}</th>
<th>{{ 'EXPORT_DOWNLOAD_LINK'|translate }}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="task in tasks">
<td style="text-align: center;">{{extractAttribute(task.resource.input,'FHIR Export User Name','valueString')}}</td>
<td style="text-align: center;">{{task.resource.authoredOn}}</td>
<td style="text-align: center;">{{extractAttribute(task.resource.input,'FHIR Export Start Date','valueString') | bahmniDate}}</td>
<td style="text-align: center;">{{extractAttribute(task.resource.input,'FHIR Export End Date','valueString') | bahmniDate}}</td>
<td style="text-align: center;"><input type="checkbox" ng-disabled="true" ng-checked="extractBoolean(task.resource.input,'FHIR Export Anonymise Flag','valueString')"/></td>
<td style="text-align: center;">{{task.resource.status}}</td>
<td style="text-align: center;"><a ng-if="task.resource.status==='completed' && task.resource.output && task.resource.output[0].valueString" href="{{task.resource.output[0].valueString}}">Download</a></td>
</tr>
</tbody>
</table>
</section>

</div>
1 change: 0 additions & 1 deletion ui/app/clinical/common/models/drugOrderViewModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -707,7 +707,6 @@ Bahmni.Clinical.DrugOrderViewModel.createFromContract = function (drugOrderRespo
};
}
viewModel.instructions = administrationInstructions.instructions;
viewModel.audit = drugOrderResponse.audit;
viewModel.additionalInstructions = administrationInstructions.additionalInstructions;
viewModel.quantity = drugOrderResponse.dosingInstructions.quantity;
viewModel.quantityUnit = drugOrderResponse.dosingInstructions.quantityUnits;
Expand Down
Loading

0 comments on commit 31ddb63

Please sign in to comment.