GSoC 2017 – Week 6

It’s the end of the 6th week and I’m happy to bring some UI to the mix. Up until now we’ve been working with the stuff that was made before. But now it’s time for new enhancements. The first part of it is enhancing the pre-theater workflow.

Along that line, we discussed what data need to be collected before a procedure, last week. I asked the community what they considered necessary, while making my own suggestions. Just as expected, there are already some implementations of data collection of a surgery.

One example was a post-op form used by a Partners In Health member. She provided screenshots of the form which they used to collect data about the procedure after it took place. It included fields to record the surgical team involved, the location of the procedure, anesthetics, complications etc. They were not collecting any data before the procedure, so they used the same form to record pre-operative diagnoses as well.

The PIH lady was kind enough to provide advice on implementing the forms as well. She gave a rough idea on how I might want to configure the provider types with metadata, and may consider adding a separate role such as surgery scheduler to assign the tasks related to theater activities.

Going by the screenshots she provided, and the data I originally proposed to collect, I came up with the following page for pre-theater data collection.

 

These are more like preliminary sketches, to get the feedback of the community. I’ll finalize them and connect the database next.

GSoC 2017 – Week 3

This week I was mostly working in checking the functionality of the system, looking at UI elements, following method calls related to surgery CRUD operations etc.

I found a few cases where a surgery validation failed when trying to enter a  emergency procedure. The problem was that the surgery associated with the emergency procedure was not properly initialized, which caused it to fail validation. A few breakpoints with IntelliJ IDEA helped to solve that. Special thanks to Gayan Weerakutti for helping me to setup debugging.

Then there were some UI elements that didn’t appear properly. Checked through files and came across a set of JSON files that were apparently used for configuring the UI, but I couldn’t understand exactly how they interacted with the other files. They aren’t imported anywhere. I’m guessing the OpenMRS classloader is specially configured to look at the path they exist and read them if they’re there.

I’ll update this post with more info in a bit.

GSoC 2017 – Week 2

I’m gonna keep this one short, at least for now. You know the reason.

Last week, we decided to replace the Joda Time library with java.time and ThreeTen-Extra library. And that’s exactly what I did this week.

The Migration

There were 3 steps to what I did.

  1. Identifying the replacement classes.
  2. Understanding the class structure to start the migration from the base classes.
  3. Figuring out the best match for a given instance of replacement.

It might not look like much, but there was quite a bit of work once I got into it. I had already started off the replacement without much thought in the previous week. But as I later realized, it’s better to first look exactly where and how the base classes are used later.

Identifying the Replacement classes

The first step was figuring out which class of Joda Time maps to which of java.time or ThreeTen-Extra (henceforth known as TTX). Some of the classes like DateTime could be replaced with ZonedDateTime from the built-in library, while others like Interval needed the help of TTX.

There were some concepts like Hours, Minutes etc. that were replaced with Duration and Period. These were used in some calculations of the scheduling algorithm.

Understanding the class structure

It’s so much easier to start from the base classes and replace the library from inside out. This is because of our lovely IDEs that continuously parse the classes and perform semantic analysis to see if we’re using methods correctly. This is quite useful as then we can clearly see if and when we’re using a method wrong somewhere, use the IDE to suggest replacements and continue our work happily.

More importantly, it helps to understand why a particular type was used in the first place. Then I can make an informed decision for the next step.

Figuring out the best match

You can’t just blindly start replacing Joda Time with whatever fits. You need to look into the context. What’s the best way to replace DateTime used in an instance where it’s used to record the available times of an operation theater? I could go with a ZonedDateTime, or use a LocalDateTime that dropped the timezone. Heck, I could record them in Instants.

For recording the available times, I went with LocalDateTime. That’s because the available times are mostly for the scheduling work done locally. I could just add a timezone later if someone from Brazil wants to see when an operation theater in Rwanda operates.

What else? Oh yeah, we talked more about moving to an official repo under OMRS. It was agreed that it’s best to move at the end of the summer, when we have a concrete, ready-to-deploy module that others can also work on. So how could I show the world that I was working, making a contribution to the open source world, with those all-important green boxes on my GitHub profile?

I could make my fork into a standalone project! Just had to contact GitHub Support center. A kind lady there resolved the issue in hours. 👌

That’s it for last week. I hope you’ll excuse the brevity, at least for now. Do check out the repo and comment on my choices. Please, I may have made mistakes. You get the joy of pointing out mistakes, I get some of dat free code inspection.

Until next time, peace!

GSoC 2017 – Operation Theater Module Workflow Enhancements

This is the official blog for my Google Summer of Code 2017 project. I am going to be working for OpenMRS, an open source project that supports healthcare delivery around the world. It feels great to have been awarded this opportunity, thank you @Team OpenMRS! 😁

My project is to work on the Operation theater module, which has been made as part of GSoC 2014. It’s used to schedule surgeries and other operation theater activities in multiple theaters. The module was written for an older OpenMRS version, so my first task is to migrate it to the latest platform.

The next steps would be to make enhancements to the workflow. There are 3 stages in any operation theater activity – pre-theater, in-theater and post-theater. The enhancements will focus on the data collection procedures during the entire workflow of an activity.

Coding officially kicks off on the 30th of May. It’s the community bonding period right now, so I’m using this time to learn more about OpenMRS. It’s a wonderful community with people willing to help and share knowledge.

After discussions with my mentor, we decided to start early. So here I’ll be posting on my progress.

Setting Up the Dev Environment

OpenMRS has a nifty tool for working on their projects – the OpenMRS SDK. It allows you to run multiple instances of OpenMRS at the same time. Hence you can easily test something on different OpenMRS versions concurrently.

The original OT module had been written for platform version 1.9.7, and the current version is 2.0.5. I used the SDK to set up the OpenMRS Reference Application 2.6, which is built on that platform and has a slew of modules bundled with it. The idea is to migrate the OT module to the latest stable release first, then provide backward compatibility if and where necessary.

I use IntelliJ IDEA as the IDE as it has great documentation and support both within the OpenMRS community and outside.

Work so far

When submitting the proposal, I had identified database changes as a key point of consideration when migrating the module. So I decided to start with that.

Out of sheer curiosity, I first tried changing just the target platform version of the module and building against that. The module got compiled successfully, but failed some tests written for the older platform. Then I skipped the tests, and imported the built module to the Ref App via the web interface. Just for the kick of it. Well, the error logs weren’t pretty. But they taught me where to look.

Specifically, they taught me that the changes of Hibernate were causing trouble. The OT module was built for Hibernate 3.x, while OpenMRS currently uses Hibernate 4.x. SessionFactory was now used in place of DbSessionFactory.

The next step was changing the module dependencies to the ones included in the latest Reference Application. Reporting, ID Generation and many other modules had come a long way forward from their older versions used in the OT module.

Then I tried building the module again. It wasn’t going to be that easy of course. Tests failed, so I skipped them again. Imported the module again, but as expected, the module couldn’t start. Database errors were all over the place.

I perused the error logs and it seemed the bean definitions in the module application context were causing the errors. Looking into the file, the errors were caused by a set of beans defined for the Appointment Scheduling module, as it apparently didn’t have its own bean definitions at that time. The current version probably does.

So I commented off those beans, and rebuilt the module. Imported the module  to the Ref App and voila! The module started! 😁

Right now the Operation theater module correctly appears in the UI, with scheduling and other functionality. Next step is to verify that it works properly, going through each action one by one. There’ll be lots of errors, lots of bug hunts. I can already feel the thrill of the hunt. Or the dread, you choose.

Next Steps

So yeah, we’re making progress. I plan to use the tests written before to identify the API calls and learn what has changed. The other option is to read the logs when errors come up.

So much to look forward to.

I’ll be sure to keep you updated.

See ya.

Materialize CSS Autocomplete with AJAX

At the time of writing this article, Materialize CSS framework’s Autocomplete widget didn’t work properly with AJAX calls. So I gave it a go myself.

Ideally, the autocomplete widget should have the following features.

  • AJAX calls must be made only after a certain minimum number of characters are entered.
  • Requests must not be sent until the user stops typing into the box. This means setting a reasonable timeout to check end of typing.
  • If a request is already on its way when the user enters more characters, the existing request must be cancelled before sending a new one.
  • Clicking a result or outside the results list must close the list.
  • Certain keys should not trigger AJAX calls.
  • The results must be scrollable with arrow keys and selectable with Enter.

The code looks something like this. A few important things are explained below it.

You can remove the timeout or escape fewer keys if you want. I used GSMArena’s search function to make a working demo, which you can test here. Note that you need to enable loading scripts from unauthenticated sources, so better try it with Chrome . Even with Chrome you need to allow loading such scripts with a teeny tiny notification that appears at the end of the address bar. The demo has images and the results link to other pages. Open the developer tools in your browser and notice how requests get cancelled if you type with small intervals. Try scrolling through the results with arrow keys. You probably don’t need to add an image to the list item or link it to another page. The idea is that you can, if you want to.

The code is pretty much self-explanatory, but let me point out a few important things.

  • I’m getting all the results from the AJAX call and appending them to a single, long string, and then appending that string to the autocomplete dropdown in one go as a single jQuery object. This is more efficient than appending each result individually, taking full advantage of the ability of jQuery to insert a chunk of html in a string. This article has a great analysis of jQuery append() method to explain why I did this.
  • Closing the autocomplete dropdown when clicking outside it – if you’re relatively new to JavaScript/ jQuery, you might not know a lot about event propagation. So you’d probably stop event propagation to close it, as suggested by the top-voted answer at this Stack Overflow question. But as others have commented there, this is a dangerous practice. The best method to do this is explained nicely by Philip Walton here.
  • Control keys such as Shift, Ctrl, Alt etc. are escaped conditionally. The conditional check uses the or operator for this, which kind of makes it long. Better alternative approaches are more than welcome.

Please suggest if you have any improvements to this code.

Until next time, then.