About USSD Flow mock app
Hi there :), welcome. This is a simple app designed for technical and non technical users. The objective is to provide a tool to wire USSD flows for visual demos very quickly and without the need to have more than a shallow JavaScript knowledge and/or a keen eye and smart hands . If you’re a seasoned engineer you may understand the code flow by reading it without going through the documentation; otherwise take a look at the guide below.
Improvements, cleanup and more details will come time to time.
A Basic flow is added by default for you to have a “template”.
note: The sample flow file and the examples here are written in plain old ES5 (with the exception of template literals) so that anyone with basic JS knowledge can understand it and avoid dealing with the complexity of TDZ, destructuring, spread operator and other ES6+ stuff, but nothing stops you from writing it in ES6+ style if you want.
See it in action
No dependencies required.
In your local machine
- Download this repository code in your computer
- Open the
/src/index.html
file in your preferred browser - Voilà
Online demo
See the demo flow herenote: In the first menu only option 1 flow is defined, you can play with the code to add the other ones or change it as you please.
How to define a flow
- The flow system consists in a combination of simple display functions and arrays.
- There’s only one mandatory display
function
nameddisplayHomeMenu
(see here) - Each display
function
should return arender
function
(see here) - All subsequent display functions are optional and they’re part of the flow you’ll design
Learning by doing
Theory tends to be hermetic, let’s see the minimum information required and then proceed with some concrete examples based on the sample flow provided on the demo.
The display functions
These are the functions of your flow, they are very simple and there’s only one mandatory function to define, the displayHomeMenu
, every other function is up to you and it will depend on the flow you want to design. The rules are simple:
Naming convention
I propose to use the prefix “display” (e.g. displayProducts
, displayPets
) but it’s just an arbitrary convention, you can use whatever name you want (e.g. doTheListThing
, x
)
Display functions definition
All display functions MUST return the render function. (see here for details)
function displayWhatever () {
return render({
content: `The whatever content`,
dataset: theWhateverDataset,
status: `the status`
})
}
The render function
The render function
accepts an object argument to tells the app the following:
- what to show:
content
- which is the data to control the next move:
dataset
- which is the display status:
status
content
property
Any arbitrary string you want to print on the display. No particular limitations with this except for very lengthy strings not being displayed nicely; up to 20 consecutive chars with no spaces are beautifully displayed but it will depend on the viewport size.
dataset
property
Two kind of datasets (Array, Function) are supported and have a specific restriction.
dataset
: Array
of objects
It must be an array of objects where each object is an item of a list of options and should contain two properties:
title
: Astring
with the option textconfirm
: a displayfunction
to be invoked when the option is selected
Each entry of the dataset has an implicit numeric index starting from 0, this index will be used when you select an option number on the “answer/send” action.
If you use the datasetToList
helper (as shown below), it will return a string to be used for the content using the index as prefix for each option item. An empty entry won’t be rendered allowing you to define non-consecutive options (e.g. starting from 1 instead of 0, or skipping a number, like 1,2,4,7)
const home = [
null, // empty entry to display a menu starting from 1 instead of 0
{ title: "Request a shipment", confirm: displaySenders }, // an option with a confirm action `displaySenders` defined elsewhere
{ title: "Check shipment status" }, // an option with no confirm action, no-op
{ title: "Repeat recent jobs" }, // no-op
{ title: "Register new user or location" }, // no-op
{ title: "Help / Other services" }, // no-op
]
function displayHomeMenu {
return render({
content: `Menu
${datasetToList(home)}`,
dataset: home
})
}
Home menu | Answer prompt | Option selection | Sender menu | |
---|---|---|---|---|
status | `options` | `answerStandby` | `answering` | `options` |
screenshot | ||||
explanation | Default home menu is displayed | User clicked on the "Answer" action and the answer selection page is displayed automatically | User types the number 1 on the num pad of the UI corresponding to the option 1 of the home menu | The option 1 has a `confirm` value assigned to the `displaySenders` display function which is invoked and the content displayed |
dataset
: Function
detail
The previous flow is designed when you have a preset of options for the user to select. What if you need arbitrary actions? Let’s say instead of having predefined option numbers you want to simulate entering an arbitrary value and whatever value you type the same “page” will be displayed after that.
function displayArbitrarySender () {
return render({
content: "Enter sender phone number",
dataset: displayPickupLocations, // note! it's the reference of a function!
status: 'answerStandby' // see status property explanation
})
}
function displayPickupLocations () {
return render({
content: `Enter pickup location
${datasetToList(pickUpLocations)}`,
dataset: pickUpLocations
})
}
var pickUpLocations = [
{ title: "Saved location 1", confirm: displayReceivers },
{ title: "Saved location 2", confirm: displayReceivers },
{ title: "Saved location 3", confirm: displayReceivers },
{ title: "Find public location near me", confirm: displayArbitraryPickupLocationCode },
{ title: "Enter a location code", confirm: displayArbitraryPickupLocationCode },
{ title: "MTN branch code", confirm: displayArbitraryPickupLocationCode },
]
Enter number | Typing number | confirm action invoked | |
---|---|---|---|
status | `answerStandby` | `answering` | `options` |
screenshot | |||
explanation | Enter sender page is displayed | User types an arbitrary value and hits "Send" | The dataset is defined as a function so the `displayPickupLocations` is invoked and the content displayed |
status
property
The status property control how the content will be displayed and which actions are available. There are 3 values available (options
, answerStandby
, final
) for you to use (of course there are more but they are for internal purpose, I wouldn’t recommend you to use them)
`options` | `answerStandby` | `final` |
---|---|---|
This is the default status if you don't pass along an explicit one, it'll infer you're presenting a list of options each one of them with a numeric value to be selected. | This is for an arbitrary value to be sent | This is for a final page, no other actions can be performed except for "Quit" which will take you back to the home page |
Writing your own flow
You can replace the sample_flow.js
file referent in the index.html at line 75 ( see the <!-- REPLACE THE SAMPLE FLOW FILE WITH YOURS-->
comment) with another file, OR you can edit the sample_flow.js file with your own code, is up to you.
Show me some action please!
PS. If something’s not working or you have any suggestion, please go to the repo and file an issue so I can track it. Thanks in advance.