Skip to content

StefanTodoran/alrite-workflow-editor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

75 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Usage Overview

It is recommended to use either Chrome or Firefox. While the editor may work with other browsers, only Chrome and Firefox are extensively tested. It is also recommended that you keep this guide document handy during the workflow editing process.

Using the Editor

The basic page setup lays out pages horizontally with their respective components underneath them. Press the plus button on the right hand side to add new pages. Click on a page's header card to edit its properties, or to add, modify, or delete its components. You can also click on a page's name to modify it.

In the bottom right you can find the collapsable menu which contains the utility buttons. Hover over these to see their labels. Using these buttons one can import a workflow from a .json file or from the server, validate a workflow, upload a workflow to the server, or change the editor's theme.

Page order is irrelevant and has no effect on the workflow, it is merely for user convenience. The only exception to this is the first page, which is the entry point for the workflow. The other page of note is the diagnosis page, which is the exit point of the workflow. Component order does matter, and components can be reordered by drag and drop. They can also be moved to different pages.

In the above image we can see the user hovering a tooltip for more information about what the input type property on the TextInput component should be. Notice the word "type" in parenthesis in the tooltip, this is the name of the property. If you wanted more information about this property, this property name in parenthesis is how it would be referred to in this usage document. The "Input Type" label is merely for convenience.

Workflow Validation

A useful safeguard / tool when working with workflows is the validation feature. This can be used by pressing the validation button in the utility menu, which looks like this:

Pressing this button will send the workflow to the server without creating a new version; instead the server will merely check for errors and return them. Any validation errors will be highlighted orange and will show an error message indicating the issue. Be careful with this feature, and do not rely on validation to be sure that a workflow is safe! Test all workflows in the app! Validation is only meant to catch certain common issues early.

Also note that the server will not allow upload of a workflow with validation errors. If you are working on a workflow and would like to save your work but have errors (for example, because the workflow is unfinished), use the save to file feature.

Branching Logic

Each page automatically will have a "Next" and "Prev" button. The "Prev" button will always return to the previous page. The "Next" button has more complex behavior and is used to create branching logic within a workflow. By default, the "Next" button goes to the page specified by the defaultLink property.

There are two ways that the defaultLink property can be overwritten: by MultipleChoice components and by some types of LogicComponent. More information can be found in these components respective sections below, however the general gist is as follows:

MultipleChoice components can overwrite defaultLink if they do not have multiselect enabled. Such a MultipleChoice component will have a link property on each of it's Choices. The link of the Choice which is selected will overwrite the defaultLink of the page when the "Next" button is pressed.

The other way that defaultLink can be overwritten is if a LogicComponent is triggered. The conditions specified in each of a page's LogicComponents are checked when the "Next" button is pressed. If a LogicComponent's condition is found to be satisfied, then it's satisfiedLink will overwrite the page's defaultLink.

If multiple LogicComponents have their conditions satisfied, the highest LogicComponent on the page will take precedence. Therefore, the order of operations is:

defaultLink < lowest LogicComponent < ... < highest LogicComponent

About ValueIDs

This section is very important so please read it carefully. ValueIDs are what make this whole thing work. For any component which takes data, whether that be a TextInput, MultipleChoice or something else, the component must have a valueID property. This serves several functions.

A component's valueID corresponds to the column of the database where that component's data will go. This means a few things. Firstly, it means that the component's valueID should clearly indicate what it is storing. For example a TextInput used by the nurses to record a child's age might be called child_age. The second implication of this is that valueIDs should almost never be changed! If you are editing a workflow and a piece of data is being collected on some page and with a certain valueID, make absolutely sure that if you modify the workflow such that the data in quesiton is being collected somewhere else it is still being collected under the same valueID. Failure to do this will result in the creation of a new column in the database, meaning there will now be multiple columns, each storing pieces of the same data. This is extremely undesirable.

WARNING This part isn't actually implemented yet!

To help try and ensure this does not happen, workflow validation will compare your workflow's `valueID`s to the existing database columns, and give you a warning if any would create a new column. When submitting again, you must indicate to override these warnings if you genuinely intend to create a new database column (such as if you are adding some new piece of data to be collected which was not being collected before). Make sure you are absolutely sure that you wish to create new database columns if you are overriding these warnings.

A component's valueID is also used to make branching logic work. Specifically, each LogicComponent has a targetValueID, which is the valueID it will look at. This does not need to be a valueID on that page, so information from previous pages can affect branching on the current page.

TLDR

  • valueIDs corresponding to database columns
  • valueIDs should not be changed almost ever
  • valueIDs are used for branching logic
  • valueIDs are global, not scoped to the page

Component Specifications

Page

title The title of the page, usually one or two words indicating the purpose of the page.
pageID A unique identifier for the page used for branching logic and page linking.
defaultLink The the next page to go to, barring any logic occuring on the page.
isDiagnosisPage Whether this is the diagnosis page or not.

By default each page has two buttons, "Next" and "Prev". While "Prev" always returns to the page which linked to this page, the page "Next" sends to may depend on logic in the page. If no logic is triggered, defaultLink is the destination. However, LogicComponents trigger when "Next" is pressed and can override this defaultLink. If there are multiple LogicComponents, tiebreaking if multiple are satisfied is done based on order (highest on page has highest precedence).

The diagnosis page is the end of the workflow. This page cannot be customized. It is included in the workflow editor so that it can be linked to, indicating the end of the workflow. There can be multiple diagnosis pages (all will link to the same page in the android app), but there probably shouldn't be.

Page Components

Paragraph (PageComponent)

text Some paragraph style text content.

A basic element representing a chunk of text on the page. It has a single property, text, which is the text content it should display.

MediaItem (PageComponent)

fileName The file name of the media to display.
label (optional) Some text caption describing the media.

WARNING The android application does not yet support MediaItem components!

Another basic element, used to display images or videos within the application. These files must be upload to the application through the ALRITE dashboard. The fileName property should be the same file name the uploaded image or video has. The optional label property displays a text caption underneath the media.

MultipleChoice (PageComponent)

valueID A unique identifier for the data collected by this component.
label A text label, generally a quesiton prompt.
multiselect Whether multiple options can be selected, or only one.

One of the basic building blocks of any workflow, this component represents both a multiple choice input with radio buttons where only one option can be selected, or a checkbox component where any number of boxes can be selected. If the component has multiselect disabled, each Choice subcomponent can have a link property that can override the Page's defaultLink property, however this property is optional. If the component has multiselect enabled, then to do branching logic use a SelectionLogic component.

Choice (SubComponent)

text The text this choice displays to the nurse.
value This can be the same as text, but is what will actually be recorded to the database if this choice is selected. You might want this to be different if some logic is done based on this choice.
link (optional) The pageID of the Page that this choice should link to if selected (not valid if parent has multiselect).

TextInput (PageComponent)

valueID A unique identifier for the data collected by this component.
label Text indicating what should be input, generally a question or prompt.
type Type of input to accept. Valid options include "numeric", "alphanumeric", "text, "any". Default means alphabetical character input only, no numbers. Any means no restrictions.
units (optional) If provided, displayed next to the TextInput, e.g. "cm".
defaultValue (optional) The does not need to start empty. If provided, the component will start with this value filled in already. The type of this should match the property (don't give a defaultValue with letters in a numeric TextInput).

Another important building block of any workflow, if there is not a designated component specifically for collecting some type of information, TextInput can almost always do the trick.

The type property can be a bit confusing, particularly "text, and "any". Text means only character input, while any means any input, including text and numbers (like alphanumeric) but also any other input type. You probably don't need to use "any", it is included for completion purposes.

Button (PageComponent)

text The button's display text, for example "Skip".
link The pageID of the Page this button opens when pressed.
hint (optional) Displayed above button detailing when/why to skip.

This component should almost never be used. Generally, navigating through the workflow should be done via the "Next" (and "Prev") button on each Page, which you can manipulate using Logic Components and MultipleChoice components. However, if for example you want a certain Page to be skipable without the nurse needing to fill out the information, that is a place where Button would be useful.

Counter (PageComponent)

valueID A unique identifier for the data collected by this component.
title A short word or phrase name for the counter, e.g. "Respiratory Rate".
hint (optional) Longer text description indicating what is being counted.
timeLimit How long to count for, given in seconds.
offerManualInput True or false, whether the counter can be bypassed by directly typing in a value.

WARNING The android application does not yet support Counter components!

The Counter component is a generalized version of the ALRITE respiratory rate counter, a specialized component designed to accurately estimate respiratory breathing rate.

The component has a button and a text input. When the user presses the button, the Counters timer will start and measure the number of times the button is pressed within the time limit. This can be used to measure respiratory rate, for example, by prompting the user to press the button each time the patient inhales. The title and hint properties can be useful for prompting the user in this way.

The text input is only displayed if offerManualInput is enabled. This can be used to bypass the rate counting process and directly input a value.

Logic Components

ComparisonLogic (LogicComponent)

type The type of comparison to be done, valid types include ">", "<", ">=", "<=", "=". The notations ">=" and "<=" mean "greater than or equal to" and "less than or equal to" respectively.
targetValueID The valueID of the component whose value will be compared to the threshold. Will be on the left hand side of the comparison.
threshold A number that is compared to the valueID, this will be on the right hand side of the comparison.
satisfiedLink The pageID of the Page to go to if the value satisfies the threshold given the comparison type.

This component is used to do logic with numbers. For example, say a page should lead to one of several different pages based on a child's temperature. We might have a TextInput with valueID "child_temp" where the child's temperature will be collected in Celsius. Perhaps we want to go to a certain page if the child's temperature is normal, and another page if they have a fever. To accomplish this, we would se the operation type to ">", since we want to see if "child_temp" is greater than some threshold. Then, we would set targetValueID to "child_temp", and threshold to say, 38. Finally, we would set the satisfiedLink to the fever page's pageID, and have the current page's defaultLink be the pageID of the normal temperature page.

For a sample workflow showing a (slightly more complex) example of using comparison branching logic, click the link below. It is more easy to digest when it is laid out visually. You will notice in the example that there are multiple ComparisonLogic components, and that their order is intentional; it reflects which should have the highest precedence in the case that multiple are satisfied.

http://54.190.44.215:8000/editor/?workflow=Fever_Logic

SelectionLogic (LogicComponent)

type Valid types include "all_selected", "at_least_one", "exactly_one", "none_selected".
targetValueID The valueID of a MultipleChoice component to look at.
satisfiedLink The pageID of the Page to go to if the selection satisfies the selection type.

ValidationLogic (LogicComponent)

type The type of comparison to be done, valid types include ">", "<", ">=", "<=", "=". The notations ">=" and "<=" mean "greater than or equal to" and "less than or equal to" respectively.
targetValueID The valueID of the component whose value will be compared to the threshold. Will be on the left hand side of the comparison.
threshold A number that is compared to the valueID, this will be on the right hand side of the comparison.

Unlike the above two logic components, ValidationLogic components are not used to create branching but rather for input validation. By default, all input components are required before "Next" can be pressed. However, to validate said inputs this component is necessary.

If the expression described by a ValidationLogic component is satisfied, the page's "Next" button will be disabled, just like it would be if an input component on the page was not filled out. Like with other logic components, multiple ValidationLogic components can be used on the same page, and the valueIDs they target do not need to necessarily correspond to components on that page. Click the link below for an example workflow where input validation is achieved using this component.

http://54.190.44.215:8000/editor/?workflow=Input_Validation

Making Changes

Running Locally

Run tsc npx -w to tell the TypeScript compiler to watch for changes. Then, run python manage.py runserver, and navigate to /editor/ in the browser. Any changes you make to the HTML, CSS or TypeScript should be updated on refresh.

Make sure you are editing the subcomponent alrite editor found in the django server's static folder. Otherwise, you will have to push and pull every time you want the server to reflect your changes.

Adding Components

  • Create an interface and documentation object for the component in components.ts
  • Add an option to the new page component ("template-new-component") in index.html
  • Create a template of the component in index.html
    • Look through existing components and the related code to make sure you understand how everything works first
    • Copy another similar component type for the structure
    • Notice how props are done: the class of the <input>, <select> or <textarea> is very important!
    • You shouldn't change much other than the id, the h1 content, and props
  • Add the HTML template component's id to templates in index.ts
  • Add the required props to requiredProps in validation.py
    • This is found in the django server's alrite directory
    • You will also need to modify the validation function with any special validation logic specific to the new component

Future Work

Below is the specification for some components that could be used to allow customization of automated diagnoses. The existing, non-customizable ALRITE application will generate some diagnoses based on inputs using some hard coded logic. The components enumerated below could be used to allow arbitrary customization of this process.

ComparisonDiagnosis (DiagnosisComponent)

type The type of comparison to be done, valid types include ">", "<", ">=", "<=", "=".
targetValueID The valueID of the component whose value will be compared to the threshold.
threshold A number that is compared to the valueID.
diagnosis A text string representing the diagnosis to assign to this patient if the comparison is satisfied.

SelectionDiagnosis (DiagnosisComponent)

type Valid types include "all_selected", "at_least_one", "exactly_one", "none_selected".
targetValueID The valueID of a MultipleChoice component to look at.
satisfiedLink The pageID of the Page to go to if the selection satisfies the selection type. diagnosis A text string representing the diagnosis to assign to this patient if the comparison is satisfied.

Such components would be the only type of component allowed on the diagnosis page, and would be run when this page is reached. One design decision that would need to be considered is whether or not these should even be seperate components, or their functionality should be somehow built into existing LogicComponents, with the differentiator of whether a given component is a regular LogicComponent or a DiagnosisComponent.

Implementation of these components would involve the following steps:

  • Change the existing implementation of components and the diagnosis page in index.ts to support DiagnosisComponents
  • Implement the components following the instructions above for adding components
  • Modify the existing validation code in validation.py on the django server
  • Build out the diagnosis logic in the android frontend
  • Update the above section on component specifications with this components
  • Add a section following the branching logic section giving an overview of how customized diagnoses are specified

About

Used to build diagnosis workflows for the Ugandan health app ALRITE.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published