For Dashboard Designers Functions
Friday, March 15, 2019 10:25 PMFunctions
Functions are the building blocks of InterActor dashboards and applications. They perform actions such as loading data or displaying information, and can be linked to each other through Triggers. Triggers are executed at specified moments in the Function's processing, or initiated by user input, and result in the execution of linked Functions. The Triggers can carry data between one Function and the next.
Both Functions and Triggers are stored in the Neo4j graph store, with Functions represented as nodes and Triggers as relations between those nodes. the InterActor Function nodes all have a :IA_Function
label, besides another label that indicates the function type. So you will find nodes with labels like :IA_Function:IA_Neo4jQuery
and :IA_Function:IA_NetworkView
. The Trigger relations have the relation type :TRIGGER
, (:SHORTCUT
or :START
if connected from a dashboard).
Each Function has a set of features in common: they inherit these from the general Function definitions. A special subset of Functions are Views, they also share a set of common features, inherited from the general View definitions.
Executing
A Function can be executed by a Trigger (coming from another Function, or from the User Dashboard). When a Function is executed, it performs the action it is designed to do, and fires outgoing Trigger events when it is done. In the following example, a TableView is executed by the 'success' Trigger event from a Neo4jQuery:
During execution, the Function may fire outgoing Trigger events, which can cause connected Functions to be executed as well.
Parameters
Each Function can behave differently, based on certain parameters. For example, a Neo4jQuery can execute a cypher
query that is passed to it as the cypher
parameter value. These values can be set on the Function, incoming Trigger,
or user prompt. The parameter values are checked for validity and stored in the Function, and can be accessed later.
More information on parameters can be found here.
Function instances and updating
By default, a Function will be executed. This means that an instance of the Function is created, performs its actions, fires outgoing Trigger events and, once it is done, it is destroyed. The Function node remains; this is merely a 'description' based on which new instances are created. A Function can be executed again and again, each time creating a new instance and destroying it after it has finished its processing.
A Function instance can also be told to persist after execution (using the $stayAlive: dashboard
parameter), keeping its data available for further processing after user input or when other Functions finish execution. Multiple instances of the same Function can co-exist. While an instance exists, it can be updated through Update Triggers. Update Triggers are similar to regular Triggers, except they specify instances of the target Function that should be updated, instead of creating a new one. The instance is specified using the $_instance
parameter, which can take one of the following values:
-
_all
: all open instances of the Function are updated. -
_previous
: the last Function instance on the execution path is updated. - Any other string: the instance with the given string as its name is updated. If it does not exist, it is created.
If the $_instance
parameter is specified, a targeted instance of the Function is created (if it does not exist) or updated (changing the data instead of creating new instances every time).
If the $_instanceUpdateOnly
parameter is set to true
, the trigger will not create a new targeted (with $_instance) instance of a function if it does not yet exist.
While a Function instance is open, its state can be accessed from each outgoing Trigger, as further described here.
List updates
For parameters that are lists, there is a special parameter #_update
available, that allows updates to specific items in the list. The #_update
parameter can contain one or multiple of the following properties:
-
add
: adds items to the list -
remove
: removes items from the list -
set
: adds or replaces items in the list -
change
: alters items in the list
Example: add
Suppose a Function parameter called myList
contains a list of numbers: [1,2,5]
. We use the #_update.add
parameter to add values 3 and 5 to the list:
#_update.add.myList: [3,5]
The resulting list in myList
will be: [1,2,5,3,5]
. Note that there is no check for uniqueness, nor is the new list ordered. The other operators (remove
, set
, and change
) do need to check for existing identical values.
Example: remove
Suppose a Function parameter called myList
contains a list of numbers: [1,2,5]
. We use the #_update.remove
parameter to remove the value 2 from the list:
#_update.remove.myList: [2]
The resulting list in myList
will be: [1,5]
. All occurrences of the number 2 are found in the list and removed.
Value identification
The operators set
, remove
and change
, need to find existing values in the list to either replace, remove or change them. In order to do this, the values in the list are compared to the values that are specified in the operator, to see if they are considered equal. Two values are considered equal if one of the following conditions hold:
- They are exactly the same (for simple values such as strings, numbers and booleans)
- The
id
properties of both values are exactly the same (in case both values are objects) - All properties of both values are exactly the same (in case both values are objects)
Example: change object
Suppose a Function parameter called myList
contains a list of objects:
[
{id: 15, name: 'Hank', age: 47},
{id: 7, name: 'Florence', age: 21},
{id: 51, name: 'Eddie', age: 35}
]
We use the #_update.change
parameter to change Eddie's name to Ed:
#_update.change.myList: [{id:51, name:'Ed'}]
The change
operator finds the object with id 51 in the list, considers it equal to the given object, and changes the name
property to "Ed".
Use of change
vs set
The change
and set
operators seem similar, in the sense that they can both change a value in the list. Consider the 'change object' example above. Suppose we want to change Eddie's information again, and use either:
#_update.set.myList: [{id:51, name:'Ed'}]
or
#_update.change.myList: [{id:51, name:'Ed'}]
The set
operator will find the object with id 51 in the list, and replace it with the new object. Note that the new object does not contain an age
property. Since the entire object is replaced, we have changed the name, but also removed the age
property. On the other hand, the change
operator will find the object with id 51 in the list, and merge the objects, i.e. replace only the properties that are defined in the new object. No properties will be removed.
The other difference is that the set
operator will add the new object if no existing object with id 51 was found, whereas the change
operator will not.
Caching
Each Function execution usually makes a call from your browser to InterActor. If the connection between the user and InterActor is slow, a significant performance boost can be achieved by caching the the Function calls. When Functions are cached, a page refresh is required to update dashboard functionality after a Function change. This is not recommended when you are in the process of developing a dashboard.
Caching can be switched on or off per user by setting the caching
property on the :IA_User
node to true
. Caching is
switched off by default.