From the pervious discussion of extending OpenLMIS to allow multiple suppliers and workflows related to requisition splitting — we have identified multiple requirements that the UI could support. This document outlines these additional requirements, and attempts to prioritize them in terms of level of effort required to implement these requirements.

CSS and SASS

There should be no special method of removing or explicitly overriding CSS — an implementer should simply use more specific CSS rules to change styles. This means that CSS styles in OpenLMIS should strive to be as general (shallow) as possible so that overriding a style can be done by creating a new CSS style. Some basic rules for doing are:

All colors, absolute spacing, and browser breakpoints should be implemented using SASS variables, so that the overall UI look and feel can be changed by creating a different *.variables.scss file that will overwrite the initial declarations in OpenLMIS.

Generic Screens (Administration Screens)

When creating new functionality, there are needs to support the addition of configuration screens so configurations can be changed after initial implementation by a non-technical user. This set of extensions might not be used often by administrations, but for implementers there is value and re-assurance that these screens are available and accessible.

Creating new screens (easy & done)

Goal: Add new functionality to the OpenLMIS-UI

Examples:

The infrastructure to create new administration screens already exists - meaning an administrative user can navigate to a new screen that is defined in a UI docker module.

Enabling features:

// Consider adding a view to see requisitions on a map
angular.module('custom-module').config(function($stateProvider){
  $stateProvider.state('requisitions.map', {
    url: '/map',
    showInNavigation: true,
    controller: 'MyCustomMapController',
    templateUrl: 'map/page.html'
  });
});

Replacing an existing screen (could be easy & not done)

Goal: Add content and functionality to an existing screen

Examples:

Options:

Build Process Option - configure the build process so that files on a similar path overwrite eachother before the UI build command is run (this would mean creating a large temporary directory). The nice thing is that if you wanted to replace the home page template, all you would have to do it place a file at `src/home/page.html` (for example). The work involved here would be defined in the NodeJS dev tools, which are shared across all repositories.

UI-Router Solution - Rewrite a UI-Router route to use the newly created view template or controller. The implementation of this in AngularJS would require a run statement to make the switch, because you would need to wait for the original state to be registered. Problem: Not clear how errors would be handled.

angular.module('custom-module').run(function($state){
  var state = $state.get('home'); // get the current home page state
  state.view.templateUrl = 'new_tempalte.html';
  // gotta figure out how to change this...
});


Custom UI-Router 'Override' -
 Allow implementers to register a route with the property 'override,' which we would recognize in UI-Router and then use the last route with a specific name if the state has the property override. This would allow us to use the error handling framework already developed in UI-Router.

Appending form elements into existing screens w/o forking (hard)

Goal: To adding a single element or field into an existing screen without forking or replacing the entire screen.

The resulting code MUST be simpler than replacing the entire screen

Extendable forms, being able to inherit form pieces

Generally people want to extend the UI in unpredictable ways, and if you give them a bit of flexibility, they will always want more

Examples:

Options:

Ideal Solution: Develop an Extendable Service


Create an abstraction service where new UI elements could register HTML templates to. This service would work much like UI-Router and allow a person to add a template and controller to the current scope. We could generically apply this code to:


angular.module('custom-module').run(function($rootScope){
  $rootScope.$on('view:requisition.actions', function(templateList, scope, additionalArguments){
    // check scope variables, and do things
    templateList.push('custom-module/template.html');
  }
});


// if we wrap this implementation into a service/factory
angular.module('custom-module').run(function(uiViewExtender){
  uiViewExtender.add(
    'requisitions.requisition', // view name, could take patterns eventually maybe
    'form-actions', // view name to replace
    'custom-module/template.html', // template to add
    10 // priority of where to load (default would be 10, maybe)
    );
  }
});

Extending Business Logic

We would want to add Javascript events so new logic can be injected in various places, the problem is there are no natural places to inject this behavior, and implementers would need to define specific places for injection.

Generic Search Result (or list) Screens

Most of the same techniques apply to changing a search results screen, and would a search result or list page.

The main problem with these screens is that they are currently written as a single page with no explicit points for extension, and its unclear what scenarios would drive changing these screens. Also the effort involved in replacing a search result screen entirely might be similar to the effort of extending the screen (as the OpenLMIS server endpoint would be the same, and does most of the lifting).

Extending search form

Goal: Add a new checkbox or variable to the existing search form, so that it is passed to the OpenLMIS server which was also extended


Scenario:

Replacing result template

This changes depending on how we implement lists, currently loops are evaluated in context, so there is no easy place to add additional code. We could create a structure to formalize item results using templates — but if new columns are added in a non-uniform fashion, we are going to have problems making sure rows and table columns match.

Modifying results shown

This is perhaps best done in a Service API that responds to the OpenLMIS-UI — as there are no existing hooks. It could be possible for services to create filter lists for transforming results, and create a simplistic event structure for acting on this data — but its messy at best.

Custom Screens with complex layouts (think Requisition Screen)

Places to add extension that shouldn't be a too hard

Form Action Button Area

This is still an issue — the ideal solution would allow implementers to add their own custom buttons to a view

Additional Table Columns and functionality

There is a need to add table columns. The good news here is that if columns are added in the RequisitionService (backend) they will be displayed in the full-supply product view with no effort as that screen is already template driven.



SIL/SELV UI Changes to OpenLMIS (from Pawel)

The following are examples of changes to OpenLMIS that SolDevlo made to SIL/SELV