Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 6 Current »

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 Styles and SASS Variability

There should be no special method of removing or explicitly overriding CSS — an implementer should simply use more specific CSS rules to change styles. All CSS styles in OpenLMIS should strive to be as 'shallow' (unspecific) as possible (and avoid the !important statement) so that its reasonable to override a style by simply creating a new CSS style.

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)

The infrastructure to create new administration screens already exists - meaning an administrative user can navigate to a new screen, that is custom in a UI docker container. When the custom UI is included into a UI image, it will be published.

Enabling features:

  • UI-Router: Allows for addition of screens with a unique URL
  • NavigationService: Allows UI-Router definitions to expose their menu items into existing navigation frameworks
// 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 really done)

Goal: Change an existing screen

Examples:

  • An implementation needs to replace the homepage with an interactive dashboard
  • A footer needs to be customized (less complicated than previous option)

Options:

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.

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...
});


// Alternatively just change $StateProvider's fallback page

Define two states with the same name, and add a property that is called "override" - worth testing what happens when there are two states with the same name


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.

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:

  • The v2 configure facility screen, which contains fieldsets of various different types, one could imagine adding a form or fieldset into the group
  • Requisition form actions, where an implementer might need to add a button

Options:

Angular Template Blocks - There is a project to add block/extend templating from templates like Jinja2 (Django/Python), Jade, or Handlebars. This library hasn't gotten much attention, and the code might turn to spaghetti quick as it relies on 'templates' to drive the extension. An ideal solution would leave very generic markup.

^ We could also use an HTML preprocessor to inject HTML templates together at build time (ie use jade blocks, to allow for templates to be overwritten) — and use a run statement to replace the template in the $templateCache. The HTML author would have to know what context they are building into. 

Create a dynamic template provider - Since we are already heavily using UI-Router, and ideal solution would be to allow developers inject content into ui-views depending on the state and specify priority order (and maybe other magic to keep it all organized). I have not found a pre-built solution for this — but the resulting code might look like:

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)
    );
  }
});

Extend `<form>` with ngTransclude - Like the two above selections, this would require a custom directive (as I can't find something that does this), but allow a user to inject elements before/after a form by registering items with the form's id element. It would make sense to extend a form element with events for onSubmit, to allow developers to link controller actions and other things to scope variables.

Using a unique idea would be a good approach — extention service stores all the HTML files/templates — there could also be a replace flag

"Extendable directive" – <div extendable="foo.bar.1" />

Targeted Directives - It also might be possible to completely replace an individual `<input />` or `<select />` element – but the difficulty would be being able to consistently target an individual element, and being able to assume that all form element actually support this ability. Issues of rending priority could also hamper development if two elements are changing the same input.

How to Extend Business Logic

  • Where would add the logic for a button injected by a template?
  • Change how stock on hand is calculated (document this)
  • Are there easy extension points for service (adding new functionality and replacing the original provider — think angular.merge/extend)

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:
  • An implementation requires that products are searched by color
See earlier note about extending a view, or extending a form element. The real trick here will be having a form submit event correctly pass the data through to the OpenLMIS server endpoint.

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

  • Fork requisition view template (overload with a method above) — there isn't much direct code that belongs to the view, and is mostly just structure. Forking this screen wouldn't be a big issue
  • Add view tabs to requisition view (probably with ui-router view) totally supported, allows for additional configuration.

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.

New table cell functionality




SIL/SELV UI Changes to OpenLMIS (from Pawel)


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

  • Localizable calendar — localaizable in all form components (people will find un-localizable parts)
  • Adding questions to columns — andding new rows and columns
  • Making sure different screen sizes and layouts work — not scroll but "wrap"
  • Being able to edit a distribution (how would you change the editablility)
  • Adding edit history screen
  • Need simplistic options to either add a button or replace a screen entirely
  • No labels