Configuring tasks with forms
Botize solves this by using plain HTML forms. In a nutshell, it works this way:
- Triggers and actions supply the markup for a HTML form as part of the data returned by the get_function_info command.
- When the user enters the task configuration page, Botize displays the trigger and the action forms as part of the user interface in the page. The user interacts with the form controls as appropriate in order to configure how the task and the action work.
- When the user tries to save the changes in the task, Botize invokes the validate_form_data command for both the trigger and the action, passing the information entered by the user as input data . Then, one of the following will happen:
- One (or the two) of the command invocations find that any of the user entered data is missing or is invalid, and returns an error message. In that case, the message is displayed to the user and the task configuration saving process is cancelled.
- All of the user entered data is valid so none of the command invocations return an error message. In that case, the task configuration saving process finishes and Botize stores the data that the user entered in both forms.
- When a task is executed, Botize supplies the form data entered by the user as part of the trigger and the action input data, in the form_data element.
Supplying a configuration form is optional for both triggers and actions: if the data returned by the get_funcion_info command has no form element, no user interface will be shown for configuring the function. However, in the case of actions that use variables of standard data types a form should always be provided, since there is no other way for the user to tell the action how should it use the data produced by the trigger.
Designing function forms
You have plenty of freedom when designing the function configuration forms for your application. Any HTML tag is allowed except for the following:
- The < form > element itself
- < input > elements of the following types: file, image, submit
< input > elements of type “button” are allowed, but they will do nothing unless you supply Javascript code to detect the button pressing.
< input > elements of the following types must have a value attribute: radio, checkbox, hidden. The same is true for < option > elements inside a < select > element.
Javascript and inline CSS are allowed, but not required.
All the form elements should have a proper name attribute. When a task is saved, Botize will scan the markup of the configuration forms provided by the get_function_info command of the trigger and the function. The values supplied by the user in all the form related elements that have a name attribute will be saved and passed to the next execution of the process_trigger or do_action in the form_data element.
For example, assume that an application returns the following HTML markup in the form element when the get_function_info is invoked for a trigger:
City: < input type=”text” name=”city” />< br /> < input type=”checkbox” name=”use_local_time” value=”true” /> Use local time
The user enters “Tokyo” in the text editor and checks the checkbox control. Then, when Botize invokes the trigger with the process_trigger command, it will include the following as part of the input data:
"form_data":{ "city":"Tokyo", "use_local_time":"true" }
Using data substitution markers
When a user creates a task with a trigger and an action that share data of standard data types, the user must instruct the action on how to use the data supplied by the trigger. This is achieved via the action configuration form.
One way to tell Botize that a certain trigger output variable should be used by the action for a certain purpose is the usage of data substitution markers, which are written by the user as part of the contents of text and textarea HTML elements of the action configuration form. A data substitution marker consists of the name of one of the output variables provided by the trigger, enclosed between . When Botize invokes the action in the context of the execution of a task, the form data passed to the action will have these markers replaced with the actual variable contents that the trigger has supplied.
For example, assume a task where the trigger returns the following in response to the get_function_info command:
... "trigger_data":{ "output_vars":{ "sensor_status":"text" } } ...
The action configured for the same task, on the other hand, returns the following in response to get_function_info:
... "form":"< label for='message' >Message:< input type='text' name='message' >" ...
The user, when configuring the task, enters the following text in the text box labeled “Message:” in the configuration form for the action:
The current sensor status is !
Once the task is properly configured, some time passes and Botize invokes the process_trigger command for the trigger, which returns the following:
... "output_data":{ "sensor_status":"Active" } ...
Then Botize invokes the do_action command for the action, and here is where the data substitution markers come into play. This is what the action will receive, note how the value of sensor_status is effectively substituting the marker in form_data/message:
... "input_data":{ "sensor_status":"Active" }, "form_data":{ "message":"The current sensor status is Active!" } ...
Listing data variables in a select element
Another way to configure how actions make use of the data variables produced by triggers is the usage of select elements that list all the available trigger variables, so that the user can select which variable to use for a certain purpose. This is achieved by tweaking the configuration form HTML
Botize recognizes a pseudo-attribute named botize-addvars and will search for it in all the select elements present in action configuration forms. When this attribute is found, Botize will render a select element that contains all the output variables of standard types generated by the trigger of the same action. The value of each of the generated option elements will be the variable name, and the displayed text will be the variable display name in the appropriate language.
The value of the pseudo-attribute will determine which variables will be included in the select element. There are three options:
- “none” will cause Botize to ignore the pseudo-attribute (so the original HTML will not be modified at all, other than for removing the attribute itself).
- “all” will cause all variables of standard types to be included.
- A comma separated list of types will cause only the variables of these types to be included, for example “int,decimal”.
For example, assume that a user's display language is English and that he is configuring a task whose trigger returns the following in response to the get_function_info command:
"texts":{ "en":{ ... "output_vars":{ "from":"From field", "send_date":"Send date", "amount":"Total amount", } }, "trigger_data":{ ... "output_vars":{ "from":"text", "send_date":"date", "amount":"decimal", "some_var":"custom_type" } }
The action for the task, on the other hand, returns the following:
... "form":"< label for='field_to_use' >Field to use:< /label >< select name='field_to_use' botize-addvars='all' />" ...
In that case, this is the actual HTML that will be rendered by Botize in the action configuration form:
< label for='field_to_use' >Field to use:< /label >< select name='field_to_use' >< select name='field_to_use' > < option value="from" >From field< /option > < option value="send_date" >Send date< /option > < option value="amount" >Total amount< /option > < /option >
Note how the some_var variable is not included because it is not of a standard type.
Assuming that the user selects the “from” field in the rendered list, this is what the action would received when Botize invokes the do_action command:
... "input_data":{ "from":"Example Smith", "send_date":"2014-02-27", "amount":"123.45", }, "form_data":{ "field_to_use":"from" } ...
See the description of the get_function_info command for details on standard vs custom variable types.
Localization of texts in function forms
Function configuration forms will usually not only contain data input elements, but also texts and labels intended to explain to the user what kind of information he is intended to supply. Botize provides you with support for providing localized versions of these texts, so that the whole form appears in the user's language in accordance with the rest of the Botize user interface.
To provide localized versions of the configuration forms texts:
- When providing the HTML markup for the form in the data returned by the get_function_info command, supply a text marker instead of the actual text. A text marker is an alphanumeric identifier enclosed in double curly brackets. For example:
- Together with the form markup, supply the texts for all markers in all the languages that your application supports. See the get_function_info command description for the exact format in which the texts must be provided.
For example, in the example configuration form shown in the previous section, you can use markers instead of actual texts in the following way:
: < input type=”text” name=”city”/ >< br/ > < input type=”checkbox” name=”use_local_time” value=”true”/ > < /br >
Then, the following would be included in the output data returned by the get_function_info command:
"form":": < input type="text" name="city"/ >< br/ >< input type="checkbox" name="use_local_time" value="true"/ >< br/ >", "texts":{ "en":{ "form":{ "city_name":"City", "use_local_time_label":"Use local time" }, "es":{ "form":{ "city_name":"Ciudad", "use_local_time_label":"Usar hora local" } } } }
Note: Do not confuse data substitution markers and text markers. They use both the same enclosing characters, but data substitution markers are written by users inside the form's text and textarea controls, while text markers are part of the HTML of the configuration form.
Ajax calls from function forms
A function configuration form may need to contact the application entry point in order to retrieve additional data to display on the form that cannot be hardcoded in the form's HTML because it depends on the status of the form controls, on the user currently logged, or on anything else. The form code can do it by itself by manually composing an Ajax call to the server where the application is hosted (or to any other server, actually), but Botize provides a simple mechanism for retrieving data from the server that should be enough for most cases. The procedure is as follows:
- The application form client code invokes the form_request method, for example when the user clicks a button in the form. This is a Javascript method that is provided by Botize and is always available in the page in which the form is being displayed. The method accepts an arbitrary input parameter of string type.
- Botize invokes the form_request command on the application entry point. The input data for the command includes the current state of all the inputs of the form, the authentication information for the current user, and the parameter passed to the Javascript method call.
- The form_request command returns a string value containing an arbitrary piece of information that will be useful for the form.
- The value returned by the form_request command is passed to the form code as the return value of the Javascript method call, and the form performs any necessary processing with it.
If something goes wrong (the server is unreachable, the request returns a HTTP status code other than 2xx, or the command response is not properly formatted), the Javascript form_request method will return null.
This mechanism allows the server to supply a single string to the form. If a more complex data structure is needed, it is recommended to return a Json encoded object, so that the form code can decode it and process it appropriately.
The page in which the form is being displayed includes a reference to JQuery. Therefore, if you prefer to perform an Ajax call manually instead of using the form_request mechanism, you can use the JQuery helper methods without having to reference the library.