UI Command Protocol
Dialob client user interface is controlled using action-based protocol between client (browser) and server (Dialob runtime). Both REST and WebSocket transports are supported with the same action protocol. REST transport is working in request-response style while WebSocket transport also supports server initiated UI updates.
Client initiates connection to Dialob filling session by opening WebSocket connection to session's socket URL or doing a GET
request to session's REST URL. Server responds to that with first message. Further client -> server messages can then be sent over WebSocket connection or with POST
request to session URL to which server responds with next message and so on.
Message protocol is using JSON
format.
UI State
A client implementing Dialob protocol, needs to keep track of following state during session:
- Items by ID
- Valuesets by ID
- Session state revision token
Items
Items are building blocks for Dialob user interface. Every item has an unique identifier and type. Items may have a list of sub-item ID-s. Items are organized in hierarchy:
Questionnaire(1) --> Page(0..n) --> Group(0..n) --> Question(0..n)
Top level item is a questionnaire that defines the title, page structure and allowed actions. There is always exactly one questionnaire item present in session.
Page item defines group structure.
Group is logical grouping item for questions.
Question is an item having user interaction.
Value sets
Value sets are lists of possible values used by selection-type questions and survey groups. One value set can be shared between several items. Value sets have unique identifier and a list of entries. Values are have key and value, where key is the answer stored in session and value is for display.
Session state revision token
Session state revision tokens are used to keep track of user interaction sequence and ensure that no messages have been lost in transit. Every message sent by server has nextRev
token attached. UI needs to keep track of this value and use it for sending the response message. Server sends back previous token value as prevRev
(omitted from first server message).
Message
Actions are encapsulated in a message structure. A message has following attributes:
- nextRev -- Session state revision token for current revision. Only used for messages coming from server.
- prevRev -- Session state revision token for previous revison. Omitted from first message coming from server.
- actions -- An array of zero or more actions.
General message object structure
{
"nextRev": "0002",
"prevRev": "0001",
"actions": []
}
Action
Actions
are used to communicate user interaction commands from client to server and UI change commands from server to client. One message can contain zero or more actions.
Every action has type attribute defining the type of the action. The rest of attributes, if any, are dependent on the action type.
General action object structure
{
"type": "NEW_QUESTION",
... payload ...
}
Actions from server to client
Action: REMOVE_ALL
On reception of this action, client is expected to clear its internal state of all items and value sets and remove all items from the UI. This action is typically sent as first action for full state dump, such as first message to client.
{
"type": "REMOVE_ALL"
}
Action: NEW_QUESTION
Server sends a new item for client to display. It has question
attribute as a payload that defines the item's properties. Every item has an unique identifier id
and a type type
. The rest of the attributes are dependent on item's type, please refer to "Handling of item types" below.
{
"type": "NEW_QUESTION",
"question": {
"id": "question1",
"type": "text",
"label": "A label",
...
}
}
Action: UPDATE_QUESTION
Server requests an update to an item. It has question
attribute as a payload that defines the item's properties. Every item has an unique identifier id
and a type type
. The rest of the attributes are dependent on item's type, please refer to "Handling of item types" below.
{
"type": "UPDATE_QUESTION",
"question": {
"id": "question1",
"type": "text",
"label": "A label",
...
}
}
Action: ANSWER_QUESTION
Server requests an update to an item's answer. It has questionId
attribute for target item and answer
attribute with the value to set.
{
"type": "ANSWER_QUESTION",
"questionId": "question1",
"answer": "Some value"
}
}
Action: REMOVE_QUESTION
Server requests to remove an item
from UI state. It has questionId
attribute for target item.
{
"type": "REMOVE_QUESTION",
"questionId": "question1"
}
}
Action: NEW_ERROR
Server sets an validation error for an item. Action has an 'error' object payload with following attributes: id
target item ID, description
error message to display. One item may have more than one validation error active at once.
{
"type": "NEW_ERROR",
"error": {
"id": "question1",
"description": "An error message"
}
}
}
Action: REMOVE_ERROR
Server requests an validation error to be removed for an item. Action has an 'error' object payload with following attributes: id
target item ID, description
error message. Matching should be done using description
attribute.
{
"type": "REMOVE_ERROR",
"error": {
"id": "question1",
"description": "An error message"
}
}
}
Action: NEW_VALUE_SET
Defines a value set used by choice-based questions. It has id
attribute for identifying the value set, items refer to this. entries
is an array of key
- value
pairs, where key
is the key of the entry and value
its display label.
{
"type": "NEW_VALUE_SET",
"id": "valueSet1",
"entries": [
{
"key": "a",
"value": "First option"
},
....
]
}
Action: UPDATE_VALUE_SET
Updates a value set, see NEW_VALUE_SET
for details.
{
"type": "UPDATE_VALUE_SET",
"id": "valueSet1",
"entries": [
{
"key": "a",
"value": "First option"
},
....
]
}
Action: REMOVE_VALUE_SET
Server requests a value set to be removed from client's UI state. Items referring to this value set lose their options. id
is the identifier of the value set to be removed.
{
"type": "UPDATE_VALUE_SET",
"id": "valueSet1"
}
Action: ADD_ROWS
Note No handling needed as this action will be deprecated in future versions.
Action: COMPLETE_QUESTIONNAIRE
Server confirms successful completion of the session. Also this action is sent by server if connection is opened to a session that is already completed. questionnaireId
contains session identifier.
{
"type": "COMPLETE_QUESTIONNAIRE",
"questionnaireId": "e58befaf6b15c6bc304ff10ae000b328"
}
Action: WILL_PASSIVATE
Server indicates that current session will be passivated to conserve resources. Next message sent from client to server will re-activate the session.
Note No handling needed as this action will be deprecated in future versions.
{
"type": "WILL_PASSIVATE",
"questionnaireId": "e58befaf6b15c6bc304ff10ae000b328"
}
Action: ACTIVATED
Server indicates that a passivated session was re-activated.
Note No handling needed as this action will be deprecated in future versions.
{
"type": "ACTIVATED",
"questionnaireId": "e58befaf6b15c6bc304ff10ae000b328"
}
Action: NOTIFY_SERVER_ERROR
Notifies about server error. This usually indicates a misconfiguration or programming issue and it shouldn't happen in normal circumstances. It is up to client how to display this for user. The session should be ended as it might be unreliable.
{
"type": "NOTIFY_SERVER_ERROR"
}
Actions from client to server
Action: ANSWER_QUESTION
This action must be sent to backend for every user action answering a question. To enable live input validation for entry fields, it could be sent for every keypress. questionId
is the item ID answered, answer
is the value.
{
"type": "ANSWER_QUESTION",
"questionId": "question1",
"answer": "Some value"
}
Action: NEXT_PAGE
User wishes to navigate to next page. No additional attributes.
{
"type": "NEXT_PAGE"
}
Action: PREVIOUS_PAGE
User wishes to navigate to previous page. No additional attributes.
{
"type": "PREVIOUS_PAGE"
}
Action: GOTO_PAGE
User wishes to navigate to a specific page. page
is the identifier for the target page item.
{
"type": "GOTO_PAGE",
"page": "page2"
}
Action: COMPLETE_QUESTIONNAIRE
User wishes to complete (submit) the session. No additional attributes.
{
"type": "COMPLETE_QUESTIONNAIRE"
}
Action: ADD_ROW
User wishes to add a new row to a multi-row group. id
is the identifier for the target multi-row group.
{
"type": "ADD_ROW",
"id": "group1"
}
Action: DELETE_ROW
User wishes to delete a row from a multi-row group. id
is the identifier for the multi row group row.
{
"type": "DELETE_ROW",
"id": "group1[1]"
}
Handling of different question types
General item structure used for all items is as follows:
{
"id": "question1",
"type": "group",
"label": "Time",
"description": "Item description",
"className": ["styleClass1", "styleClass2"],
"answered": true
...
}
Mandatory attributes are:
id
- Unique identifier of the itemtype
- Type of the itemlabel
- Display label of the itemanswered
-true
if the item (question) is answered
Optional attributes for all item types:
className
- an array of user-entered "style class" namesdescription
- markdown text for longer description of the itemvalue
- current value (answer) of the question, in caseanswered=true
Other attributes are depending on the item type
Item type: questionnaire
For every session there is exactly one item of questionnaire
type. It should be considered as a root item from which the UI rendering should get started.
Attributes
items
- array of page item IDs, in that order, that are defined for this questionnaireactiveItem
- ID of the currently active page itemavailableItems
- array of page item ID's that can be navigated toallowedActions
- array of action types that are accepted by server at this moment. Should be used to render navigation elements in UI
{
"id": "questionnaire",
"label": "Example dialog",
"type": "questionnaire",
"className": [],
"items": ["page1"],
"activeItem": "page1",
"availableItems": ["page1"],
"allowedActions": ["ANSWER_QUESTION"],
"answered": false
}
Item type: group
A normal item group or a page. If this is referenced from items list from questionnaire item, it should be considered as a page, otherwise it is a guestion group.
A group referenced by items
of a rowgroup is a row within that multi-row group.
Attributes
items
- array of item IDs, in that order, contained withing this group
Special case
If this group has a className of survey
then this group is considered a "Survey Group". This group has also a valueSetId
attribute pointing to a value set that has defined common options for all survey
questions contained within this group.
An example of a group or page
{
"id": "group1",
"label": "Question group",
"description": "Question group description\n",
"type": "group",
"className": [],
"items": ["question1", "question2"],
"answered": false
}
An example of a survey group
{
"id": "group3",
"label": "Survey group",
"type": "group",
"className": ["survey"],
"items": ["question8", "question9", "question10"],
"answered": false,
"valueSetId": "group3_valueset1_valueSet"
}
Item type: rowgroup
A group that can contain several rows of questions.
Attributes
items
- array of zero ro more item IDs, in order, pointing togroup
items for rows.
{
"id": "group2",
"label": "Multi-row group",
"type": "rowgroup",
"className": [],
"items": ["group2[1]"],
"answered": false
}
Item type: text
A text entry field. Should be rendered as a single line text input box.
Special case: textbox
If textbox
is defined as one of the className
items, it should be rendered as a multi-line text box. Could be rich text.
Special case: choice
If text question has valueSetId
attribute defined, it should be rendered as a single selection, for example, a dropdown.
Special case: survey
If survey
is defined as one of the className
items, it should be rendered as a radio-selection of items defined in enclosing survey-group's value set.
Answer format is "string"
A single-line text entry
{
"id": "question1",
"label": "A text question",
"type": "text",
"className": [],
"answered": false
}
A multi-line text entry
{
"id": "question1",
"label": "A text box question",
"type": "text",
"className": ["textbox"],
"answered": false
}
Single choice question
{
"id": "question1",
"label": "A single choice question",
"type": "text",
"className": [],
"valueSetId": "question1_valueset1_valueSet",
"answered": false
}
Survey choice question
{
"id": "question8",
"label": "First question",
"type": "text",
"className": ["survey"],
"answered": false
}
Item type: number
Integer entry field, positive or negative
Ansewer format is an integer: 0
{
"id": "question1",
"label": "An integer question",
"type": "number",
"className": [],
"answered": false
}
Item type: decimal
Decimal entry field, positive or negative
Ansewer format is decimal: -6.5
{
"id": "question1",
"label": "A decimal question",
"type": "decimal",
"className": [],
"answered": false
}
Item type: boolean
A boolean flag question. Could be rendered as a checkbox. It should be made clear for user between non-answered and false states.
Answer format is boolean: true
or false
A single-line integer entry
{
"id": "question1",
"label": "A boolean question",
"type": "boolean",
"className": [],
"answered": false
}
Item type: date
Date entry field. Could be rendered as a date picker.
Answer format is YYYY-MM-DD "2016-12-25"
{
"id": "question1",
"label": "A date question",
"type": "date",
"className": [],
"answered": false
}
Item type: time
Time entry field. Could be rendered as a time picker.
Answer format is HH:MM "11:34"
{
"id": "question1",
"label": "A time question",
"type": "time",
"className": [],
"answered": false
}
Item type: array
Multi-choice field. User can select multiple options from a value set.
Answer format is an array of strings ["option1", "option2"]
{
"id": "question1",
"label": "A multi-choice",
"type": "array",
"className": [],
"valueSetId": "question1_valueset1_valueSet",
"answered": false
}
Item type: note
A read-only note field. Its label
should be rendered as markdown text.