Skip to content

Commit

Permalink
Phani, Bindu | BAH-3117 | Ability to add, display and update Notes se…
Browse files Browse the repository at this point in the history
…ction in OT Scheduling (#647)

* Add Modal to create OT Notes

* Make notes scrollable

* Add Redirection on Save

* Add ToolTip

* Fix css for day view.

* Add tests

* Add Validations for Create Note

* BAH-3092 | Show primary diagnoses in OT list view (#631)

* BAH-3092 | add capability to show primary diagnosis in OT list view

* BAH-3092 | refactor to display latest diagnoses and test fixes

---------

Co-authored-by: Ashish Kurian <[email protected]>

* Fix build issues

* Integrate with Backend for Day view

* Update CSS and date

* Bindu | add notes save and get support for week view

* Bindu, Phani | BAH-3117 | Integrate Update API to the UI

* Bindu | Fix test cases

* Bindu | Change note resource to notes

* Fix tests

* Phani | A-1205015570874061 | Ability to delete existing notes on the OT Scheduling page. (#650)

* Make css of notes text configurable and Add notes delete template

* Add css for hover and fix translation

* Fix Update notes functionality

* Add delete note functionality

* Fix fetch date issue

* Fix tests

* Fix UI validations and CSS

* Fix CSS in notes modal

---------

Co-authored-by: Phanindra-tw <[email protected]>
Co-authored-by: kavitha-sundararajan <[email protected]>
Co-authored-by: Ashish Kurian <[email protected]>
Co-authored-by: Phanindra-tw <[email protected]>
  • Loading branch information
5 people authored Jul 24, 2023
1 parent 2efd6d0 commit 9ea001c
Show file tree
Hide file tree
Showing 13 changed files with 708 additions and 33 deletions.
14 changes: 13 additions & 1 deletion ui/app/i18n/ot/locale_en.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"DATE": "Date",
"DISCARD": "Discard",
"SAVE": "Save",
"UPDATE": "Update",

"ADD_SURGICAL_APPOINTMENT": "Add Surgery",
"EDIT_SURGICAL_APPOINTMENT": "Edit Surgery",
Expand Down Expand Up @@ -114,5 +115,16 @@
"ACTUAL_TIME_ADDED_TO_KEY":"Actual time added to ",
"OT_SURGICAL_BLOCK_ACROSS_MULTIPLE_DAYS_CONFIRMATION_MESSAGE": "Are you sure you want to create a surgical block across days?",
"MOVING_KEY": "Moving",
"FROM_KEY": "from"
"FROM_KEY": "from",
"EMPTY_NOTES_ERROR": "Note cannot be empty",
"NOTE_TITLE": "Note",
"FROM": "From",
"TO": "To",
"FROM_DATE_BEFORE_TO_DATE_ERROR": "From date should be before To date",
"DATE_OUT_OF_RANGE_ERROR": "Please select date within the valid range",
"DELETE_NOTE_TITLE": "Delete Note",
"YES_KEY": "Yes",
"NO_KEY": "No",
"DELETE_NOTE_MESSAGE": "Are you sure you want to delete this note?",
"NOTES_PLACEHOLDER": "Enter a maximum of 150 characters"
}
3 changes: 2 additions & 1 deletion ui/app/ot/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ Bahmni.OT.Constants = (function () {
defaultCalendarStartTime: '00:00',
weekDays: {"Monday": 1, "Tuesday": 2, "Wednesday": 3, "Thursday": 4, "Friday": 5, "Saturday": 6, "Sunday": 7 },
defaultWeekStartDayName: 'Sunday',
providerSurgicalAttributeFormat: 'org.openmrs.Provider'
providerSurgicalAttributeFormat: 'org.openmrs.Provider',
notesUrl: RESTWS_V1 + '/notes'
};
})();

207 changes: 202 additions & 5 deletions ui/app/ot/controller/otCalendarController.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,176 @@
'use strict';

angular.module('bahmni.ot')
.controller('otCalendarController', ['$scope', '$rootScope', '$q', '$interval', 'spinner', 'locationService', 'surgicalAppointmentService', '$timeout', 'appService', 'surgicalAppointmentHelper',
function ($scope, $rootScope, $q, $interval, spinner, locationService, surgicalAppointmentService, $timeout, appService, surgicalAppointmentHelper) {
.controller('otCalendarController', ['$scope', '$rootScope', '$q', '$interval', '$state', 'spinner', 'locationService', 'surgicalAppointmentService', '$timeout', 'appService', 'surgicalAppointmentHelper',
function ($scope, $rootScope, $q, $interval, $state, spinner, locationService, surgicalAppointmentService, $timeout, appService, surgicalAppointmentHelper) {
var updateCurrentDayTimeline = function () {
$scope.currentTimeLineHeight = heightPerMin * Bahmni.Common.Util.DateUtil.diffInMinutes($scope.calendarStartDatetime, new Date());
};
var updateBlocksStartDatetimeAndBlocksEndDatetime = function () {
$scope.blocksStartDatetime = $scope.weekOrDay === 'day' ? $scope.viewDate : moment($scope.weekStartDate).startOf('day');
$scope.blocksEndDatetime = $scope.weekOrDay === 'day' ? moment($scope.viewDate).endOf('day') : moment(Bahmni.Common.Util.DateUtil.getWeekEndDate($scope.weekStartDate)).endOf('day');
};
$scope.isModalVisible = false;
$scope.notesStartDate = false;
$scope.notesEndDate = false;
$scope.isEdit = false;
$scope.showDeletePopUp = false;
$scope.styleForBlock = function (index) {
if (index === 6) {
return { 'border-right': '.5px solid lightgrey'};
}
};
var setValidStartDate = function (viewDate) {
const currentDate = new Date(viewDate);
$scope.validStartDate = $scope.weekDates[0];
while (currentDate > new Date($scope.weekDates[0])) {
const prev = new Date(currentDate);
currentDate.setDate(currentDate.getDate() - 1);
if ($scope.notesForWeek[currentDate]) {
$scope.validStartDate = prev;
break;
}
}
};
var setValidEndDate = function (viewDate) {
const currentDate = new Date(viewDate);
$scope.validEndDate = $scope.weekDates[6];
while (currentDate < new Date($scope.weekDates[6])) {
const prev = new Date(currentDate);
currentDate.setDate(currentDate.getDate() + 1);
if ($scope.notesForWeek[currentDate]) {
$scope.validEndDate = prev;
break;
}
}
};

$scope.showNotesPopup = function (weekStartDate, addIndex) {
const currentDate = new Date(weekStartDate);
if (addIndex === undefined) {
addIndex = 0;
}
currentDate.setDate(currentDate.getDate() + addIndex);
$scope.notesStartDate = currentDate;
$scope.notesEndDate = currentDate;
$scope.isModalVisible = true;
$scope.isDayView = $state.weekOrDay === 'day';
if (!$scope.isDayView) {
setValidStartDate(currentDate);
setValidEndDate(currentDate);
}
};
$scope.showNotesPopupEdit = function (weekStartDate, addIndex) {
const note = $scope.getNotesForDay(weekStartDate, addIndex);
const currentDate = new Date(weekStartDate);
$scope.otNotesField = note;
currentDate.setDate(currentDate.getDate() + addIndex);
$scope.notesStartDate = currentDate;
$scope.notesEndDate = currentDate;
$scope.isModalVisible = true;
$scope.isEdit = true;
$scope.dateOutOfRangeError = false;
};
$scope.closeNotes = function () {
$scope.isModalVisible = false;
$scope.startDateBeforeEndDateError = false;
$scope.emptyNoteError = false;
$scope.dateOutOfRangeError = false;
$scope.notesStartDate = undefined;
$scope.notesEndDate = undefined;
$scope.otNotesField = '';
$scope.isEdit = false;
};
$scope.setNotesEndDate = function (date) {
$scope.dateOutOfRangeError = date === undefined;
$scope.startDateBeforeEndDateError = date < $scope.notesStartDate;
$scope.notesEndDate = date;
};

$scope.setNotesStartDate = function (date) {
$scope.dateOutOfRangeError = date === undefined;
$scope.startDateBeforeEndDateError = date > $scope.notesEndDate;
$scope.notesStartDate = date;
};

$scope.setNotes = function (notes) {
$scope.otNotesField = notes;
if (notes) {
$scope.emptyNoteError = false;
}
if (notes && notes.id) {
$scope.notesId = notes.id;
}
};
$scope.openDeletePopup = function (weekStartDate, index) {
if (weekStartDate) {
$scope.currentDate = new Date(weekStartDate);
$scope.currentDate.setDate($scope.currentDate.getDate() + index);
}
$scope.showDeletePopUp = true;
};
$scope.closeDeletePopup = function () {
$scope.showDeletePopUp = false;
};
$scope.deleteNotes = function () {
var noteId;
if ($scope.weekOrDay === "week") {
noteId = $scope.notesForWeek[$scope.currentDate].noteId;
}
surgicalAppointmentService.deleteNoteForADay(noteId || $scope.noteId);
$scope.showDeletePopUp = false;
$state.go("otScheduling", {viewDate: $scope.viewDate}, {reload: true});
};

$scope.saveNotes = function () {
if ($scope.startDateBeforeEndDateError || $scope.dateOutOfRangeError) {
return;
}
if (!$scope.otNotesField) {
$scope.emptyNoteError = true;
return;
}
if ($scope.isDayView) {
surgicalAppointmentService.saveNoteForADay($scope.viewDate, $scope.otNotesField);
} else {
surgicalAppointmentService.saveNoteForADay($scope.notesStartDate, $scope.otNotesField, $scope.notesEndDate);
}
$state.go("otScheduling", {viewDate: $scope.viewDate}, {reload: true});
};

$scope.updateNotes = function () {
if ($scope.startDateBeforeEndDateError || $scope.dateOutOfRangeError) {
return;
}
if (!$scope.otNotesField) {
$scope.emptyNoteError = true;
return;
}
var note;
if ($scope.weekOrDay === "week") {
note = $scope.notesForWeek[$scope.notesStartDate];
}
surgicalAppointmentService.updateNoteForADay(note ? note.noteId : $scope.noteId, $scope.otNotesField);
$state.go("otScheduling", {viewDate: $scope.viewDate}, {reload: true});
};

var heightPerMin = 120 / $scope.dayViewSplit;
var showToolTipForNotes = function () {
$('.notes-text').tooltip({
content: function () {
var vm = (this);
return $(vm).prop('title');
},
track: true
});
};
const getNotes = function () {
if ($scope.weekOrDay === 'day') {
return surgicalAppointmentService.getBulkNotes(new Date($scope.viewDate));
} else if ($scope.weekOrDay === 'week') {
return surgicalAppointmentService.getBulkNotes($scope.weekStartDate, getWeekDate(7));
}
};
var init = function () {
var dayStart = ($scope.dayViewStart || Bahmni.OT.Constants.defaultCalendarStartTime).split(':');
var dayEnd = ($scope.dayViewEnd || Bahmni.OT.Constants.defaultCalendarEndTime).split(':');
Expand All @@ -20,6 +179,9 @@ angular.module('bahmni.ot')
$scope.editDisabled = true;
$scope.cancelDisabled = true;
$scope.addActualTimeDisabled = true;
$scope.otNotes = "";
$scope.isModalVisible = false;
$scope.showDeletePopUp = false;
$scope.dayViewSplit = parseInt($scope.dayViewSplit) > 0 ? parseInt($scope.dayViewSplit) : 60;
$scope.calendarStartDatetime = Bahmni.Common.Util.DateUtil.addMinutes($scope.viewDate, (dayStart[0] * 60 + parseInt(dayStart[1])));
$scope.calendarEndDatetime = Bahmni.Common.Util.DateUtil.addMinutes($scope.viewDate, (dayEnd[0] * 60 + parseInt(dayEnd[1])));
Expand All @@ -28,14 +190,22 @@ angular.module('bahmni.ot')
$scope.rows = $scope.getRowsForCalendar();
return $q.all([locationService.getAllByTag('Operation Theater'),
surgicalAppointmentService.getSurgicalBlocksInDateRange($scope.blocksStartDatetime, $scope.blocksEndDatetime, false, true),
surgicalAppointmentService.getSurgeons()]).then(function (response) {
surgicalAppointmentService.getSurgeons(),
getNotes()]).then(function (response) {
$scope.locations = response[0].data.results;
$scope.weekDates = $scope.getAllWeekDates();
var surgicalBlocksByLocation = _.map($scope.locations, function (location) {
return _.filter(response[1].data.results, function (surgicalBlock) {
return surgicalBlock.location.uuid === location.uuid;
});
});
if (response[3] && response[3].status === 200) {
$scope.noteForTheDay = response[3].data.length > 0 ? response[3].data[0].noteText : '';
$scope.noteId = response[3].data.length > 0 ? response[3].data[0].noteId : '';
} else {
$scope.noteForTheDay = '';
$scope.noteId = '';
}
var providerNames = appService.getAppDescriptor().getConfigValue("primarySurgeonsForOT");
$scope.surgeons = surgicalAppointmentHelper.filterProvidersByName(providerNames, response[2].data.results);
var surgicalBlocksBySurgeons = _.map($scope.surgeons, function (surgeon) {
Expand All @@ -48,7 +218,34 @@ angular.module('bahmni.ot')
return $scope.isSurgicalBlockActiveOnGivenDate(surgicalBlock, weekDate);
});
});

$scope.getNotesForWeek = function (weekStartDate, index) {
const date = new Date(weekStartDate);
if (index === undefined) {
const notesForAWeek = {};
response[3].data.map(function (note) {
notesForAWeek[new Date(note.noteDate)] = note;
});
return notesForAWeek;
}
return _.filter(response[3].data, function (note) {
const currentDate = new Date(date);
currentDate.setDate(date.getDate() + index);
return new Date(note.noteDate).getDate() === (currentDate).getDate();
});
};

if ($scope.weekOrDay === 'week') {
$scope.notesForWeek = $scope.getNotesForWeek();
}

$scope.getNotesForDay = function (weekStartDate, index) {
var notes = $scope.getNotesForWeek(weekStartDate, index);
return notes.length > 0 ? notes[0].noteText : '';
};

$scope.blockedOtsOfTheWeek = getBlockedOtsOfTheWeek();
showToolTipForNotes();

var setOTView = function (providerToggle) {
$scope.providerToggle = providerToggle;
Expand All @@ -66,8 +263,8 @@ angular.module('bahmni.ot')
};

$scope.isSurgicalBlockActiveOnGivenDate = function (surgicalBlock, weekDate) {
return Bahmni.Common.Util.DateUtil.isSameDate(moment(surgicalBlock.startDatetime).startOf('day').toDate(), weekDate)
|| moment(surgicalBlock.endDatetime).toDate() > weekDate;
return Bahmni.Common.Util.DateUtil.isSameDate(moment(surgicalBlock.startDatetime).startOf('day').toDate(), weekDate) ||
moment(surgicalBlock.endDatetime).toDate() > weekDate;
};

$scope.intervals = function () {
Expand Down
10 changes: 10 additions & 0 deletions ui/app/ot/directives/otNotes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use strict';

angular.module('bahmni.ot')
.directive('otNotes', [function () {
return {
restrict: 'E',
require: '^otCalendar',
templateUrl: "../ot/views/notesModal.html"
};
}]);
1 change: 1 addition & 0 deletions ui/app/ot/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@
<script src="directives/otCalendar.js"></script>
<script src="directives/otWeeklyCalendar.js"></script>
<script src="directives/otCalendarSurgicalBlock.js"></script>
<script src="directives/otNotes.js"></script>
<script src="directives/otCalendarSurgicalAppointment.js"></script>
<script src="directives/multiSelectAutocomplete.js"></script>
<script src="directives/stringToNumber.js"></script>
Expand Down
47 changes: 46 additions & 1 deletion ui/app/ot/services/surgicalAppointmentService.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,54 @@ angular.module('bahmni.ot')
v: "custom:(id,uuid," +
"provider:(uuid,person:(uuid,display),attributes:(attributeType:(display),value,voided))," +
"location:(uuid,name),startDatetime,endDatetime,surgicalAppointments:(id,uuid,patient:(uuid,display,person:(age))," +
"actualStartDatetime,actualEndDatetime,status,notes,sortWeight,bedNumber,bedLocation,surgicalAppointmentAttributes,patientObservations))"
"actualStartDatetime,actualEndDatetime,status,notes,sortWeight,bedNumber,bedLocation,surgicalAppointmentAttributes))"
},
withCredentials: true
});
};
this.getBulkNotes = function (startDate, endDate) {
return $http.get(Bahmni.OT.Constants.notesUrl, {
method: 'GET',
params: {
noteType: 'OT Module',
noteStartDate: startDate,
noteEndDate: endDate
},
withCredentials: true
});
};

var constructPayload = function (noteDate, note, noteEndDate) {
const payload = [];
const currentDate = new Date(noteDate);
// eslint-disable-next-line no-unmodified-loop-condition
while (currentDate <= noteEndDate) {
payload.push({
noteTypeName: "OT module",
noteDate: new Date(currentDate),
noteText: note
});
currentDate.setDate(currentDate.getDate() + 1);
}
return payload;
};

this.saveNoteForADay = function (noteDate, note, noteEndDate) {
const payload = noteEndDate != null ? constructPayload(noteDate, note, noteEndDate) : [{
noteTypeName: "OT module",
noteDate: noteDate,
noteText: note
}];
const headers = {"Accept": "application/json", "Content-Type": "application/json"};
return $http.post(Bahmni.OT.Constants.notesUrl, payload, headers);
};

this.updateNoteForADay = function (noteId, note) {
const headers = {"Accept": "application/json", "Content-Type": "application/json"};
return $http.post(Bahmni.OT.Constants.notesUrl + "/" + noteId, note, headers);
};
this.deleteNoteForADay = function (noteId) {
const headers = {"Accept": "application/json", "Content-Type": "application/json", withCredentials: true};
return $http.delete(Bahmni.OT.Constants.notesUrl + "/" + noteId, headers);
};
}]);
Loading

0 comments on commit 9ea001c

Please sign in to comment.