Open Web Apps, common application functionality, and coexistence with refapp apps

Continuing the discussion from Integrating Open Web Apps with the rest of the application:

I’ve been thinking more about how we’re going to have build common application functionality with Open Web Apps, and how they’ll work alongside apps in the Reference Application.

One idea: we move the reference application’s CSS style guide out of the UI Commons module and into a new “UI Commons Open Web App” we create for this purpose. (We’ll need to switch the standardEmrPage decorator in the App UI module to refer to this, and add a way to package OWAs in the reference application.)

We should also put some common reference application things like page decoration and global navigation in the same UI Commons OWA. (I guess we start doing these in AngularJS, and think about how to generalize across technologies as a separate piece of work.) While doing this, we should also refactor so that it takes the minimum number of modules running to build an OWA that’s consistent with the refapp UI.

For example currently the refapp gets session details from a REST service in the App UI module (which itself requires the uiframework, appframework, uicommons, and webservices.rest modules). We could move this REST service up one level to the appframework module, but we might actually want to move it all the way up to the webservices.rest module. (@burke, @pascal, and others, how do we feel about moving more application logic into our core REST web services? E.g. having a sessionLocation set in an HTTP session attribute, and the logic for deciding which provider account is active. A refactoring of the stuff here.)

Also, on the thread I forked from, I mentioned that we’ll need a way to let OWA zip files add apps and extensions to the App Framework. That’s still true, and we should go ahead and ticket this.

Any thoughts? (I wrote a bit of code for this on my last flight, so I will share that soon.)

Darius, I think you are correct that we need to move out common css and some js out of UI commons, but I do not think we should distribute it in a common OWA.

I think the more appropriate approach is to create a bower or webpack package, which is basically a git repository with tagged versions. In such a case every app would be using a specific version of such a package. The result is that every app has its own copy of the common css and js, which is versioned.

It would be up to the app developer to upgrade to a newer version of common css and js (which is very easy with tools like bower or webpack). The benefit is that a developer can test the app regardless of the common OWA app installed. The app can be reliably deployed to different servers without worrying about incompatible versions of css/js. I think it is a very important aspect as css and js are particularly tricky and even a small change in css can completely destroy the view.

2 Likes

@raff, doesn’t that mean that an OWA will have different look and feel depending on what version of the style guide it was built against (as opposed to what it’s running against)? That seems undesirable.

What you propose makes sense when it comes to js and reusable components, but I would think that to have common styling across one installation we need to have common styles served at one place in that location, not copied (with potentially different versions) into each different app…

2 Likes

Yes, it is what I was thinking about, but you are right that it makes more sense for js than for css. After all one css shared across modules worked for us in the old UI as we didn’t change it much. Also restyling of a distribution is easier done when you have one shared css. I support the OWA approach for css then.

1 Like

@darius, I’m setting up a sprint starting this Friday and I could include creating the UI Commons OWA. I’ve created a an issue:

We’ll need a separate issue to actually remove sass files from the ui commons module once we commit to the new approach and we are able to distribute OWA with the reference application.

I’d like to put the header in the UI Commons OWA as well. See:

And also add the breadcrumbs navigation to the header component.

2 Likes

@raff, I’m glad we’re thinking alike, because I wrote some code on the plane that you can refer to in the tickets. I just checked in code at https://github.com/djazayeri/openmrs-owa-uicommons, and . (Particularly see the readme section on “WHAT I DID TO PULL THINGS IN FROM THE UICOMMONS MODULE”.)

This depends on some uncommitted changes I have, to add a sessioncontext resource. I couldn’t decide whether to put it in appframework or in webservices.rest.

What do you think about this question I asked in the first post in the thread?

My 2¢…

This makes sense to me, since I think session info (and maybe other stuff I can’t think of right now) will be useful for developers wanting to build apps using just the Platform (not RefApp).

Regarding adding apps to the RefApp home screen, we could use an optional proprietary extension like openmrs_app_descriptor to contain the AppDescriptor. I’m not personally a huge fan of this though, because I like the idea of people building apps using the Platform only plus possibly just the OWA module to host their app. I don’t feel like it’s such a big deal for people to perform a one-time configuration to get their app on the home screen.

What if we made App Framework aware of OWA instead of the other way around? That way:

  1. developers who just want to use Platform+OWA can do so
  2. the openmrs_app_descriptor can be detected when App Framework is installed and ignored otherwise

I think I agree with @raff’s first reaction to creating an OWA for CSS/UI components. In my view (and I think the spec’s view), OWAs should be completely self-contained and should be installable on any platform that supports the OWA standard. @sunbiz demonstrated this by installing an OWA built for DHIS2 into OpenMRS, and it worked!

I do agree that different styling across the RefApp is not ideal, but in other app ecosystems it’s usually up to the app developer to upgrade their app. I much prefer the idea of creating something like a Bower package in order to not introduce OWA dependencies and keep our OWAs fully self-contained and installable anywhere.

My personal preference would be to have the following:

$ bower install openmrs-ui#2.3.1

This would include all our SCSS/CSS for that version, plus common HTML fragments like the header, breadcrumbs and whatever else we want to make available to app developers (whether they’re building an OWA or their own standalone app).

I’m interested to hear @sunbiz’s thoughts on this.

2 Likes

Definitely curious to hear what @sunbiz thinks.

I think our philosophy should be that these are OpenMRS Open Web Apps, not generic OWAs that could run on OpenMRS, DHIS2, or any arbitrary container. We’re trying to build an application out of coherent apps that form an EMR, not a collection of arbitrary apps.

And we should have some proprietary OpenMRS extensions that we recommend people follow. Examples:

  • Add extensions like “openmrs-require-core-version” and “openmrs-require-modules” that the OWA module should check before starting the OWA
  • Add extensions like “openmrs-app-descriptor” for plugging into App Framework
  • We should recommend (but not require) that OWAs include something like “< !-- import implementation-specific global CSS here – >” and we replace this with a macro preprocessor.
  • We should recommend (but not require) that where possible OWAs depend on a “uicommons” OWA, and import the style guide CSS from this.

I agree that we should publish versions of the style guide CSS to bower, in addition to making it available via a uicommons OWA.

Also, I agree that we should make appframework depend on OWA, rather than the other way round.

1 Like

I think we should try to release most of the RefApp elements as components in a UI Commons OWA, including the CSS, JS and component logic. That way we can ensure that people can reuse as much as possible and keep not just the look, but also the way it works. I am of the opinion that the yo script generated index.html should point to the UI Commons OWA, so that we can standardize the way OWA’s are going to look, and be part of the RefApp.

I feel that we should try to be very frugal in adding custom extensions. Off course, these custom extensions when put in the right place, will be ignored by other containers. I think OWAs are fairly easy to re-purpose as browser extensions, mobile apps etc and that is the strength of the standard. Loose coupling is the strength of the web and we should try to keep it that way. So, I believe that the dependencies should be through bower or yo scripts, but not through a manifest config etc. The appframework should find the OWAs and display on the homepage or another jump menu location.

OWA should be dependent on the webservices and those should be fairly stable across versions. So we want to version the resources and the OWA developer will support through different versions of the resources. I forget what its called, but there is a pattern for feature on/off that I think is a good idea. Same should be the case with module APIs being available or not and them, the OWA behaves different based on what features are available. If a OWA needs a module, it might as well tell the user, please install this module by clicking here or something like that.

I think it’s fine to add some standard compliant proprietary extensions to the manifest, since they’ll be ignored in other contexts.

OWA should be dependent on the webservices and those should be fairly stable across versions

This is a bit tricky, because the set of modules that contribute to the resources exposed by the web services could be different. Are you assuming that people will only build apps using Platform vA.B.C + OWA or RefApp vX.Y.Z (with no module changes)? In my opinion it’s okay to do version checking in the OWA Module, but ideally OWAs should be robust enough to fail gracefully if required.

I still don’t like introducing OWA interdependency. Can we not just move the UI commons stuff to the OWA Module (in addition to a Bower package) instead of into another OWA?

Over time I think we should encourage owa dependencies (and I’ll sound like a broken record - reuse components provided by other OWAs), but in a loosely coupled way. I now remember that the design pattern is called feature toggles. The features in OWAs should depend on resource representations, if the exact resource (or its exact representation) isn’t available, it should be able to fallback and present features that the current representation has, or ignore completely if a fallback isn’t available. This gallery of components is quite interesting. By webservices, I meant not just platform webservices.rest, but any webservices basically, including those that are provided by modules.

1 Like

No. “Just show all OWAs” is not a sufficient solution. :slight_smile:

(1) Some OWAs, like the uicommons one we’re discussing here, are not meant to be directly accessed by an end user. (2) OpenMRS is built around the idea that different users have different roles and different privileges. We need a custom extension to either define how App Framework adds this, or at least to define a required privilege to access the OWA.

This should definitely be possible. But the dynamism and power of the OpenMRS ecosystem is in its modules, and most new functionality intentionally lives in modules for years before making it into openmrs-core. So many or most interesting OWAs will require specific OpenMRS modules to be loaded.

That’s all I’m saying. That and let’s have a Bower package with our UI commons stuff so that people building apps that are not OWAs can still use all our awesome UI stuff.

A big (and incorrect) paraphrasing of what I meant.

This should not be the OWA developer’s role to judge if this is useful for the implementation or not. It should be up to the implementer to add the app to the menu, launch page or wherever the appframework allows and the implementer wants to display.

The permissions and privileges are set by the OpenMRS implementer. The OWA standard provides for permissions that it needs and not what permissions it gives. The implementer should be able to create what apps, what resources should be available to the logged in user of the OWA, as well as the OWA for somethings like settings.

Sorry for misrepresenting what you were saying. I didn’t know how else to interpret “The appframework should find the OWAs and display on the homepage or another jump menu location.”

This may allow good-enough behavior for the reference application to automatically create homepage links for all apps. (Though peeking at the docs, it seems that “permissions” in the manifest are “not on a current W3C standards track, but…supported on the Firefox OS platform”) But I wouldn’t pursue this because (a) not every OWA has an obvious end-user-useful home screen, e.g. the uicommons one, and I don’t want superusers to always see a pointless “UI Commons” app on their homescreen; and (b) not all apps belong on the homescreen.

I take your point that these OWAs are supposed to be flexible and non-opinionated about where they are placed.

My main point is that a distribution author needs to be able to configure the way that a server is set up programmatically, in a reproducible way, that doesn’t require an admin to manually specify where apps need to go.

The theoretically correct approach is that “this is the job of distributions,” so we need to ensure we provide a good programmatic API that lets distro authors load OWAs as part of the installation.

But I still prefer for OWAs to have better default behavior when a user installs them. E.g. the Concept Management OWA that Rafal is leading a sprint to build should automatically show up on the “Configure Metadata” screen of the reference application when you add the OWA.

So I will still push for having a proprietary extension that lets an OWA author indicate (via the existing appframework mechanism) where they would like their OWA to show up in the refapp’s UI.

I feel the default “configuration” in a distribution should be through settings. You have the default setting (global property), which lists which apps should be shown on the launch page (homepage). UI commons OWA may not belong to this default list. Concept management, might belong to Configure metadata. The folder notion to organize apps is well assimilated among users, but its upto the user to put them in a folder. So, the default is it just shows up on the OWA App management applist, and then the distribution author when distributing it puts it in a folder, but the administrator can create own folders or put it directly on the launch page.