Authorable Workflow Codelab 6: Working with advanced UX widgets

This is an advanced Codelab. It covers the following concepts:

How to handle data structures.

  • Types: List, Structure, Dictionary.
  • A combination of these types.

How to use a dynamic template.

How to use table widgets.

  • Use UX widgets.
  • Construct different tables: A read-only table and a selectable table.
  • Use tables: Select something in a table and set the input or read the output.

How to build an Atlas signal display.

  • Construct a table or combo-box with multiple selections of Atlas products..
  • Create a table with all the fields.
  • Single-select fields to get values. Then, don't allow a duplicate selection.

How to use a scenario to test the tool.

How to test the Codelab.

In previous codelabs, we worked with some basic types: string and number. Data structure is how we expand the descriptive power of these basic types in order to build and organize data.

Depending on the type of data, and the data to be used, there are many types with different benefits and costs. The benefits are out of scope for this simple primer. This exercise covers the patterns of data sets and recommends a data structure that you can use for your workflows.

This type of data structure organizes data of the same kind in a sequence. The following are examples:

  • List of songs on a CD: ["1st song", "2nd song", "3rd song"]
  • List of students in a class: ["abe", "becky", "connie", "dustin"]
  • List of multiple lists: [["cd1:1st song","2nd song","3rd song"], ["cd2:1st song","2nd song", "3rd song"], ["cd3:1st song", "2nd song", "3rd song"]]
  • Size(): This function determines the number of items in a list.
  • ListAppend(): This function adds items to a list.
  • ListAppendIf(): This function adds items to a list if some condition is true.
  • Contains(): This function finds a single item from a list.
  • ContainsAny(): This function finds one of many items from a list.

Build a list of songs from CDs

Objective: Build "list1" and use functions to build a list of lists.

Task: Create an action node, InitList, and use the following storage directives:

  1. cdSongs = ["1st song","2nd song","3rd song"]
  2. listOfCds = []
  3. listOfLists = ListAppend(arg: listOfLists, value: cdSongs)
  4. listOfLists = ListAppend(arg: listOfLists, value: cdSongs)
  5. listOfLists = ListAppend(arg: listOfLists, value: cdSongs)
  6. numOfCds = Size(arg: listOfCds)

The action node created looks like the following list:

564bac18a3295f48.png

Use a key value widget to display a list

Objective: Build "list1," "list2," and "list3," and use functions to build a list of lists.

Task: Create a page node, DisplayList, and use the following form field:

information display: key-value

Label : I have ${numOfCds} cds in my collection.

  1. Cd 1 = listOfCds[0]
  2. Cd 2 = listOfCds[1]
  3. Cd 3 = listOfCds[2]

The following is a Sample solution workflow:

7faaf26f7b0c6a8.png

61e23638a533299d.png

Structure is a type of data structure. In this type, the collection of data describes one kind of a thing by the use of basic types in order to build a more complex type. The data used doesn't have to all be of the same type.

The structure has a field name and data for the field. The field name is case-sensitive, must be unique within the structure, and have no spaces or special characters.

Objective: Create a song structure.

All songs have a title, a list of artists (whether without an artist or with many artists), a publish date, and a length in seconds. You can also mix things up with multiple types, like string, list, date, and number.

{ Title: "song", Artists: ["artist 1", "artist 2"], PublishData: 2018-01-01, Length: 450 }

A dictionary data structure is like a real dictionary. It's used to look up unique names and to ensure that they have the correct meaning attached to them. You can use a dictionary data structure to map a unique name (a field) to a list of strings.

For example, a teacher has three class periods and a list of students. You can use a list of lists to organize the classroom information, as follows:

{ Period1: ["student 1", "student 2", "student 3"], Period2: ["student 1", "student 2", "student 3"], Period4: ["student 1", "student 2", "student 3"]}

The advantage of the Dictionary data structure is the ease of field data manipulation. SetField and ClearField are powerful functions to use with this data structure.

The following are example functions related to the Dictionary data structure:

Build a dictionary of cd songs

Objective: Build dictOfCds, and use functions to build a dictionary of cds.

Task: Create action node, InitDictionary, with the following storage directives:

  1. dictOfCds = {}
  2. dictOfCds = SetField(dictionary: dictOfCds, field: "Cd1", overwrite: true, value: cdSongs)
  3. dictOfCds = SetField(dictionary: dictOfCds, field: "Cd2", overwrite: true, value: cdSongs)
  4. dictOfCds = SetField(dictionary: dictOfCds, field: "Cd3", overwrite: true, value: cdSongs)
  5. numOfCds = Size(arg: FieldList(dictionary: dictOfCds))

The following action node is displayed:

92941cf9706e38b8.png

Objective: Build "list1", "list2", "list3", and use functions to build a list of lists.

Task: Create page node, DisplayDict, and use the following form field:

information display: key-value

Label: I have ${numOfCds} cds in my collection.

  1. Cd 1 = Map(key: "Cd1", map: dictOfCds)
  2. Cd 2 = Map(key: "Cd2", map: dictOfCds)
  3. Cd 3 = Map(key: "Cd3", map: dictOfCds)

The following page node is displayed:

c1b3555db60a1a6.png

8e50753ee31a7208.png

You can put these data structures, List, Structures, and Dictionary, together and nest them in different ways to represent very complex, real-life things. A CD songlist. A library shelf full of CDs. You can pick and choose from these data structures to to display or manipulate data in different ways.

The Support Automation team can create new help functions and structures for you. The following are categories of other data structures that we support:

  • Money: FormatMoney
  • Date and Time: TimestampToString(), ToMicros(), ToNanos().
  • IP address: UnpackIPAddress()

The following is a summary list:

list {
  struct {
    display_text: string
    selected: bool
    value: string
  }
}

The following example shows the summary list used for UX widgets:

[{display_text: "summary one", selected: false, value: "val_1"},
{display_text: "summary two", selected: false, value: "val_2"},
{display_text: "summary three", selected: false, value: "val_3"}]

BuildDisplayOptions() is a useful function.

The following is an example of the BuildDisplayOptions() function used with the summary list for UX widgets:

BuildDisplayOptions(display_strings:{val_1: "summary one", val_2: "summary two", val_3: "summary three"}, values:["val_1", "val_2", "val_3"])

The following is a read-only table list:

list {
  list {
    <string> or <int>
  }
}

The following is an example of the BuildDisplayOptions() used with a read-only table list:

[["val 1", "val 2", "val 3", "val 4", "val 5"],
["val 6", "val 7", "val 8", "val 9", "val 10"]]

The following is a selectable table list:

list {
  struct {
    row_data: list {
      <string> or <int>
    }
    selectable: bool
    selected: bool
    value: any
  }
}

The following example shows the selectable table list used for UX widgets:

[
{row_data:["val 1", "val 2", "val 3", "val 4", "val 5"], selectable: true, selected: false, value: 0},
{row_data:["val 6", "val 7", "val 8", "val 9", "val 10"], selectable: false, selected: false, value: 1},
{row_data:["val 11", "val 12", "val 13", "val 14", "val 15"], selectable: true, selected: false, value: 2}
]

In this part of the codelab you'll use generic data to dynamically alter a Redwood snippet. You'll also learn how single- and multi-select dynamic tables work.

Dynamic template and tables step 1: basic setup

Objective: Create an action node to generate some data to use for this section.

  1. Set up the following storage directives:

Storage directive

table_Values

myGaia

myEmail

Equal to:

[{row_data:["Multi-select dynamic Overflow Table","OT is the value we'll assign to this choice","An overflow table is useful when you are trying to show too many columns and need hide some important things"], selectable: true, selected: false, value: "OT"},{row_data:["Multi-select dynamic table","MS is the value for this choice","This is useful too - but harder to read the content"], selectable: true, selected: false, value: "MS"},{row_data:["Single-select table - this one","ST is the value for this one", "A table is a table is a table is a table"], selectable: true, selected: false, value: "ST"},{row_data:["Get me out of the workflow!","OUT is the value for this one"], selectable: true, selected: false, value: "OUT"}]

ToString(arg:CallerGaiaId())

atlas:GAIA:PrimaryEmailAddress(gaia: CallerGaiaId())

The following action node is displayed:

11180ca5493be5eb.png

In this step, you'll create a single-select table to show the options in table_Values. You'll set a variable to show the choice made, and to make it visible on the next screen:

  1. Add a table to the page.
  • Name it field_1.
  • Set it to Single for row selection.
  • Row data = table_Values.
  • Add two columns to the table (click Add Column).
  1. Add a storage directive on the page to store the selection made by the user.
  • table_Selection = ouput.field_1
  1. Set the Next step to "new page".

The following page is displayed:

b3f2dfc81c41974e.png

Objective: Set up and show the selection in a dynamic template.

Task: In this step, you'll create a single-select table to show the options in table_Values. You'll set a variable to show the choice made, and to show it on the next screen.

  • Create a Redwood snippet with variable placeholders. Use the text below:

This is a dynamic snippet:

  1. Did you know your GAIA ID is: ${gaia} ?
  2. Because I know your GAIA ID, I can get your email: ${email}
  3. You choice from the previous table was: ${myvariable}

Dynamic template and tables, step 3b: add snippet to AW

Objective: Show the selection in a dynamic template.

Task: Create a static text field and add the newly-created snippet to it in one of two ways:

Method 1

Click the text field. In Redwood, you'll notice that a toolbar shows up on top. Select Insert item > Snippet.

  • What you see is what you get (WYSIWYG): You'll see the preview of the snippet. You can easily edit it.

91063d2a848b4486.png

53eacb06e9456cb2.png

Method 2

In the text box type TEXT_SNIPPET:<id>.

  • Example: TEXT_SNIPPET:9175757
  • No preview of the snippet is given.
  • Has the same result as Method 1.

53b16aded8b9e695.png

Dynamic template and tables, step 3c:- make it dynamic

Objective: Show the selection in a dynamic template.

Click the 3-dot menu of the static text control screen and select Manual dictionary.3c-2; Use the values in the manual dictionary to modify the snippet dynamically. The manual dictionary replaces the variables in the snippet with variables from the workflow.

Then, set the manual dictionary value to the following:

{myvariable: table_Selection, gaia: myGaia, email: myEmail}

3c-3: Set Next step field to new decision node.

fb854347bc5becf1.png

Objective: Decide what's next.

Now that you've made a selection on what you want to see, let's use your selected value to decide what's next.

There are four possible outcomes (four branches):

  1. Branch 1 (multi-select, overflow table)
  • Condition: table_Selection == "OT"
  • Goes to a new page called "OverflowTable."
  1. Branch 2 (multi-select, normal table)
  • Condition: table_Selection == "MS"
  • Goes to a new page called "MS."
  1. Branch 3 (single-select table)
  • Condition: table_Selection == "ST"
  • Goes to an existing page (the first page that you created).
  1. Branch 4 (terminate workflow-)
  • Condition: ELSE
  • Workflow is completed.

5380c1b1248bd281.png

Objective:

Show a multi-select overflow table in a new page. This is the outcome from Branch 1 of Step 4.

In the page for Branch 1, follow these steps:

  1. Create a new table.
  • Name it field_1.
  • Create three columns and name them.
  • Row data is called table_Values.
  1. Use the "cog" for table settings
  • Set Row selection to Multiple.
  • Select Overflow columns.
  • Move the Overflow columns marker as you see fit.
  1. Add a new storage directive to store the selection(s) you made.:
  • Set table_Selection to equal output.field_1.
  1. Set Next step to New page. The new page shows the multiple selections that you've made.

c1242f7ca8fad983.png

Now you'll show a multi-select table in a new page. This is the outcome for Branch 2 from Step 4. This outcome is almost identical to that from Branch 1. However, it's without the overflow and is therefore harder to read.

In the page for Branch 2, follow these steps:

  1. Create a new table.
  • Name it field_1.
  • Create three columns and name them.
  • Row data is called table_Values.
  1. Use the "cog" for table settings.
  • Set Row selection to Multiple.
  • Do not select Overflow columns.
  1. Add a new storage directive to store the selections that you made.
  • Set table_Selection to equal output.field_1.
  1. Set Next step to go to the new page set in Step 5.

b35ff2de224ec1d5.png

Now that you've made selections from the multi-select table, follow these steps to use the same snippet used in Step 3 in order to show it:

  1. Create a static text field and add the snippet to it.
  2. Click the 3-dot menu of the static text control screen to select Manual dictionary.
  3. The values in the manual dictionary are used to modify the snippet dynamically. Set the manual dictionary value to the following:

{myvariable: str_table_Selection, gaia: myGaia, email: myEmail}

  1. Set Next step to the first "action" node of the workflow.

70111254be4bc086.png

The following is the completed workflow for the dynamic template's behavior:

e644577c7d652854.png

https://redwood.corp.google.com/#/composer/workflowItem/9194436

Once you create your workflow, you can test it with scenarios to add mock data. Follow these steps:

  1. In your workflow, click on the 3-dot menu on the right side of "workflow info," and select Scenarios.
  2. Define a name and description.
  3. Click ADD MOCKS.
  4. Select the node you want to use in the scenario that you're building.
  5. Enter the scenario mock data.
  6. Save the workflow.
  7. Click LAUNCH.

2f48c6eb2f8a8956.png

Run your workflow in Scenarios

If your workflow requires a case_id, you have to enter a real case_id to launch your workflow in Scenario's environment.

ca59ea2a9d162adf.png