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.
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.
- 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
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.
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:
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
)
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
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
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.
Two kind of datasets (Array, Function) are supported and have a specific restriction.
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
})
}
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 },
]
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)
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.
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.