Displaying HTML entry forms based on login session in reference application

@ssmusoke did you just forget to put the uuid in quotes? Can you copy and paste here the exact expression you are using?

@dkayiwa: sessionLocation.uuid==‘86863db4-6101-4ecf-9a86-5e716d6504e4’ that is the expression i have.

Can you try appContextModel.sessionLocation.uuid?

I tried to debug this and sessionLocation.uuid==‘86863db4-6101-4ecf-9a86-5e716d6504e4’ works well if i pass the session Location object to the javascript engine via javascriptEngine.setBindings(). So the reason this does not work is because session Location object is passed as a SimpleObject which is just a hash map that looks like: sessionLocation={uuid=2131aff8-2e2a-480a-b7ab-4ac53250262b, display=Isolation Ward, name=Isolation Ward, …}

Other expressions like patient.uuid work well because the actual patient object mapper is passed as: patient=org.openmrs.module.coreapps.contextmodel.PatientContextModel@43f4ef20, instead of SimpleObject.

In summary, after this line: https://github.com/openmrs/openmrs-module-coreapps/blob/master/omod/src/main/java/org/openmrs/module/coreapps/page/controller/patientdashboard/PatientDashboardPageController.java#L83 when i do something like below, all is well: contextModel.put(“sessionLocation”, sessionContext.getSessionLocation());

If i have got this right, then we need a ticket to look into it.

Thanks @dkayiwa for looking into this. That was pretty smart.

Good research @dkayiwa. This is annoying!

The idea is that we want to have simplified JSON-equivalent context models so that they can be evaluated on either the server or client side, so we actually want to go in the direction of how session location is currently doing it.

Can you tell if there is some way to bind a JSON-equivalent object into the JavaScript engine?

@dkayiwa so where do we go from here?

@ssmusoke the easy alternative is to simply use: sessionLocation.get('uuid')=='86863db4-6101-4ecf-9a86-5e716d6504e4'

That should work well.

@dkayiwa Will this work in the “Show If” form metadata as that is where the rule is defined? cc @jmpango

@ssmusoke yes it should work.

I created a ticket for this bug at

@ssmusoke, @jmpango, note that when we fix this bug, “sessionLocation.get(‘uuid’)” will stop working, and you’ll need to go back to the originally-intended “sessionLocation.uuid”.

@dkayiwa, I looked into this more, and it’s very annoying. There’s no nice way to put any Map-like object in the ScriptEngine Bindings and have it be treated as a JavaScript object. (I’m surprised about this.)

Of course there are a couple of hacky workarounds:

  1. For each contextModel property that’s a Map, we evaluate a script that defines it as a variable within the engine using json, prior to evaluating our actual script. Here is a pull request for this approach.
  2. Use NativeObject as shown here.

The second is arguably cleaner, but we’d have to do a deep conversion of all the Maps-within-Maps to be NativeObjects, so I chose the first approach.

I’d like some feedback about this before deciding whether to apply it.

@mogoodrich FYI

My vote is that we apply this. Thanks @darius for the pull request!

@dkayiwa, Please let me know when you merge the pull request so that I can test it out.

@darius:

Note that we have been using the sessionLocation.get(‘uuid’) approach (and similiarity things like user.get(‘fn’).hasPrivilege(‘View Patients’)), so this change will break these, and the following downstream tests in appui (I assume):

I don’t mind changing things on our (PIH) end, because this does seem like a better approach, but I’ll need to coordinate, and I don’t know if anyone else has been building “require” expressions using this model? (probably not?)

I vote that this gets changed in coordination with the Reference Application 2.4 release that should happen this quarter.

(I’m not in a position to do the coordinating though!)

From a PIH perspective, coordination = just let me know when this change gets merged in.

In that case…I just merged it. And I’ll release a version of AF with this for use in the refapp 2.4 release.

@jmpango, @ssmusoke, FYI this change has been made. It will be included in Reference Application 2.4, and you can use it today in App Framework 2.8 (which Mark just released). So from then doing sessionLocation.get('uuid') will stop working.

You can see an example of it here on the devtest02 server. Basically it’s an extension with “require” set to:

sessionLocation.uuid=='b1a8b05e-3542-4037-bbd3-998ee9c40574'

Also, FYI, doing this via hardcoding UUIDs is probably not the best idea for a distribution that you intend to deploy at multiple sites. You may want to check out what is done here, i.e. this require clause will trigger if your session location has the “Inpatient” tag.

hasMemberWithProperty(sessionLocation.tags, 'display', 'Inpatient')

@darius Thanks for the update and getting the release through. We are looking to use a custom modules that deploys MDS packages for locations and any forms. Therefore the UUIDs are known before hand, is there any gotcha we need to prepare for in this case?

@darius Deployed the change but I am running into an error here

The problem is with the BaseOpenMRSMetadata property of retired which has getRetired() and isRetired() - tested with both 1.11.5 and 1.11.6-SNAPSHOT using the same module versions as devtest02

The only difference that I am seeing is that I am using metadatadeploy 1.7 vs 1.5 on devtest02 and devtest01. I am running tests to see if that difference is the root cause of the issue — I have upgraded to 1.7 on devtest02 and the example still works. So I am now stumped