Logic Editor In Katapult Pro

As the Katapult Pro software platform continues to grow and mature, it is becoming more important for our clients to have control over the various configurable aspects of the software. The Logic Editor in Katapult Pro gives users an interface where users can build out logical statements and scriptlets, analogous to Microsoft Excel functions, with as much or as little complexity as they require.

 

Statement Structure

These Logic Editor blocks are organized in a tree-like structure, as shown in Figure 1. The root of the tree is the top-leftmost “node” (a "Logical And” expression here), and the leaves are connected by the lines extending from the root. Leaves can be “dead-end” blocks or branch out into other trees.

 

The data in Figure 1 has three trees in it. The first is the outer tree with a “Logical And” expression as its root, and leaves containing two other trees. The top inner tree has a root of “Equal” and leaves of a data block and a literal text block, while the bottom inner tree has a root of “Not Equal” and leaves of a data block and a literal text block. Just like with an Excel function, these expression trees dictate the conclusion of the Logic statement.

Figure 1

 

Logic Blocks

Logic Editor statements are made up of Logic blocks. Figure 2 depicts an expanded “Logical And” expression block. All blocks have a header and a collapsible details section. The block type determines what sections are seen when the block is expanded (reference Figure 2).

The block header has:

 

The three-dot menu has several options for manipulating the block (reference Figure 2). You can:

 

Confirmation prompts appear when an action you are about to take (deleting or pasting) may result in data loss. This prompt can be bypassed by shift-clicking on the action.

There are four types of Logic blocks that can be used to make statements. These are: (1) expression blocks, (2) data blocks, (3) literal blocks, and (4) procedure blocks.

Figure 2

 
 

Expressions

Expressions are the most fundamental Logic block. Akin to Excel functions, they tell the interpreter to take one or more input values, perform an operation on them, and hand back the resulting value. Because of this input-output system, expression blocks can be nested into trees, where the result of one expression can be an input for another, "parent" expression. Remember, the final “return value” of the entire statement is whatever the root block returns; if the root block is an expression, the statement’s return value is whatever that expression resolves to.

 

Each expression block has a drop down menu, which allows the user to select the expression’s operator. A description of the currently selected expression is displayed at the bottom of the Logic block under "Description." The block’s footer details the data type that the block will return, as well as a list of the expression’s inputs and their expected types. The leaves of a block are the block’s inputs (often called arguments). Order matters here. This expected order is the order of the items listed in the block’s footer.

image(145)

Figure 3

 

Expressions as Arguments

Take a look at Figure 3. This expression (using the “Count If” operator) will count the number of items in a given list (the first argument) that pass a given condition (defined in the second argument). In order for this example block to be evaluated correctly, the first leaf of this block would need to be a block which produces a list, and the second leaf of this block would need to be a block which results in a true or false statement. Note: in this statement, both arguments are expressions, but the first produces a list (“List Object Values” returns a list of items) and the second is an expression that will be called for each of that list’s items.

 

Some expressions loop through a given list, which means that the user might want to access each item of the list individually. For these kinds of expressions, this can be done by setting the Item Data Key value, which is located below the description. You can input what you want the name of a given item taken out of the list to be into the text box, then you can use this identifier in any data block of any subtree of this expression whenever you want to access the value of this item. For reference, this kind of behavior is shown in Figure 3 in the data block with the word “item”.

 

Expression Operators

Every expression block uses an operator, selected from the dropdown, to determine what the block does with its inputs. The tables below catalog the complete set of operators available in the Logic Editor, along with the data type each one returns and the inputs it expects.

 

Logical Operators
Type Description Expects Returns
GET_FROM Treats arg-1 as a data source and arg-2 as a path to get from that source [object, text] any
EXISTS Whether arg-1 exists (is any value besides null, undefined, or empty text) [any] boolean
NOT_EXISTS Whether arg-1 does not exist (is null, undefined, or empty text) [any] boolean
IS_FALSE Whether arg-1 is (or is considered) false [any] boolean
IS_TRUE Whether arg-1 is (or is considered) true [any] boolean
AND Logical "and" (all arguments are true) [any] (chainable) boolean
OR Logical "or" (at least one argument is true) [any] (chainable) boolean

 

Comparison Operators
Type Description Expects Returns
EQUAL Whether arg-1 has the same value as arg-2 [any, any] boolean
NOT_EQUAL Whether arg-1 does not have the same value as arg-2 [any, any] boolean
GREATER_THAN Whether arg-1 is numerically greater than arg-2 [any, any] boolean
LESS_THAN Whether arg-1 is numerically less than arg-2 [any, any] boolean
GREATER_OR_EQUAL Whether arg-1 is numerically greater than or equal to arg-2 [any, any] boolean
LESS_OR_EQUAL Whether arg-1 is numerically less than or equal to arg-2 [any, any] boolean

 

Control Flow Operators
Type Description Expects Returns
FALLBACK Returns arg-1 unless it is null/undefined, then returns arg-2 [any, any] any
IF_ELSE If arg-1 (condition) is true, returns arg-2, otherwise arg-3 [expression, any, any] any

 

Mathematical Operators
Type Description Expects Returns
SUM Returns the sum of all arguments [number] (chainable) number
SUBTRACT Subtracts arg-2 from arg-1 [number, number] number
MULTIPLY Returns the product of all arguments [number] (chainable) number
DIVIDE Divides arg-1 by arg-2 [number, number] number
ROUND Rounds arg-1 to decimal places specified by arg-2 (default 0) [number, number] number
FLOOR Rounds arg-1 down to the nearest integer [number] number
CEIL Rounds arg-1 up to the nearest integer [number] number
MAX Returns the largest of all arguments [number] (chainable) number
MIN Returns the smallest of all arguments [number] (chainable) number

 

List/Array Operators
Type Description Expects Returns
SUM_LIST Returns the sum of arg-1's list items [list] number
INCLUDES Whether arg-2 is present in arg-1 (list or text) [list/text, expression] boolean
EXCLUDES Whether arg-2 is not present in arg-1 (list or text) [list/text, expression] boolean
SOME Whether at least one item in arg-1 meets arg-2's condition [list, expression] boolean
EVERY Whether every item in arg-1 meets arg-2's condition [list, expression] boolean
FILTER Returns subset of arg-1's items that satisfy arg-2's condition [list, expression] list
UNIQUE Returns a list of unique values from arg-1 [list] list
LENGTH Counts list items in arg-1 (or characters if arg-1 is text) [list/text] number
COUNT Counts arg-1's list items that satisfy arg-2's condition [list, expression] number
FIND Returns first list item from arg-1 satisfying arg-2's condition [list, expression] any
MAKE_LIST Creates a list from the provided arguments [any] (chainable) list
MAKE_LOOKUP Creates a lookup from arguments (each a 2-item key-value list) [list] (chainable) object
MAP Maps arg-1's items to a new list by applying arg-2 to each [list, expression] list
JOIN Joins arg-1's items with delimiter arg-2 (default: none) [list, text] string
SPLIT Splits arg-1 text into a list on delimiter arg-2 [text, text] list
LIST_KEYS Returns a list of object keys from arg-1 [object] list
LIST_VALUES Returns a list of object values from arg-1 [object] list
FLATTEN_LIST Concatenates sub-array elements recursively up to specified depth [list, number] list
MAX_LIST Returns the largest item in arg-1 [list] number
MIN_LIST Returns the smallest item in arg-1 [list] number
REDUCE Reduces arg-1 to a single value using arg-2 expression and arg-3 initial value [list, expression, any] any
CONCATENATE_LISTS Concatenates all arguments into a single flat list [list] (chainable) list

 

Text/String Operators
Type Description Expects Returns
CONCATENATE Concatenates all arguments into a single string [text] (chainable) text
PAD_START Pads beginning of arg-1 to length arg-2 with string arg-3 [text, number, text] text
PAD_END Pads end of arg-1 to length arg-2 with string arg-3 [text, number, text] text
REPLACE Finds all instances of arg-2 in arg-1 and replaces with arg-3 [text, text, text] text
TO_UPPER_CASE Makes every character in arg-1 upper case [text] text
TO_LOWER_CASE Makes every character in arg-1 lower case [text] text

 

Conversion & Format Operators
Type Description Expects Returns
CONVERT_UNITS Performs unit conversion: arg-1 value, arg-2 source unit, arg-3 target unit, arg-4 precision [number, text, text, any] number
FORMAT_TIMESTAMP Formats epoch milliseconds (arg-1) to format string (arg-2) using Luxon tokens [number, text] text

 

Object/Lookup Operators
Type Description Expects Returns
CONCATENATE_LOOKUPS Merges all arguments (objects) into a single object [object] (chainable) object

 

Pattern Matching Operators
Type Description Expects Returns
MATCHES_REGEX Returns true if arg-1 matches regex built from pattern arg-2 and flags arg-3 [text, text, text] boolean

 

Data

Data blocks produce values from within the Logic statement’s data source (compare these to the data contained in cells and sheets that Excel functions have access to). Each implementation of Logic in Katapult Pro has a data source object that the editor can access (for example, the Quality Control Logic Editor provides data access to a Katapult Pro job, its metadata, photos, nodes, etc.). Data blocks, together with expression blocks, allow you to develop meaningful statements and functions with real data.

 

The exact value returned from a data block is specified with the “Path” input in the block’s details section. Without the path, data blocks would always return all of the data the statement has access to, which is not at all useful. Instead, the path input allows you to enter the location of the data you want to use.

 

Paths are formed by stringing entity names together with periods. This is called a dot-delimited path; it is similar to slash-delimited paths like what you see in a filesystem or URL, but using periods instead of forward slashes. Take a look at the job JSON data in Figure 4. If the user wanted to access the job’s name, their path input would be simply name, and a data block with that path would return “Colin Test”. A more complicated example: say the user wanted to know the value of the “Done” attribute of the first node. The path would look something like this:

 

nodes.-N6iz7gzKB2N5x_UZvLe.attributes.done.*

 

Notice: in this example, we know the node’s ID (-N6iz7gzKB2N5x_UZvLe) but we might not know the key under the done attribute (as this key can be different from job to job). So instead of guessing, we use the * wildcard. This path delimiter effectively says: I don’t know what the exact key is here, just give me the first thing you can find. In this case, it finds the one and only key under “done” and completes the path. Thus, the value “false” is returned.

Figure 4

 

List Items

In expressions where you’re working with list data, the items from that list can be accessed with the value given to the expression’s Item Data Key input. In the data block of Figure 3, the value of the item data path becomes whatever list item the expression is currently on, so the data block under the “Equal” expression (item.firstName) will return whatever is that list item’s “firstName” property.

 

Literal

A literal block allows you to define a one-time, unchanging value for use in calculations (think constants). Users can define several types of literal values:

 

If you wanted to see if some data value was equal to the number 0, you would use an “Equal” expression block, a data block to access the value in question, and a literal block with “Value Type” of “Number” and a “Value” of 0.

 

Procedures

A procedure block allows you to:

 

Figure 5 depicts the structure of a procedure block. All variables are defined inside the procedure block’s details section ("condition" and "count"). When you add a new variable, it is added to the list inside the block, and it becomes the root of a new tree attached to the procedure block. You can then build a statement on this new root whose result can be accessed by using the given variable name.

Figure 5

 

These “steps” are run from top to bottom, and as each statement is evaluated, the result is added to the Logic statement’s dataset under the provided variable name. Subsequent procedure steps have access to these variables. Their values can be accessed by creating a data block and entering the variable name in the “path” input. You can see an example of how variables are accessed in Figure 5, where the “condition” and “count” variables are used in the ending if-else block.

 

The final value of a procedure Logic block is whatever the last block (called the “return” block) evaluates to. Variables created in a procedure are “scoped” (available to) the procedure block and its leaves only. Variables are not permanently added to the dataset; they are unavailable outside of the procedure in which they were defined.