Task Report Pattern

Interface patterns give you an opportunity to explore different interface designs. Be sure to check out How to Adapt a Pattern for Your Application.

Goal

Provides a simple way to create and display an Appian task report. This page explains how you can use this pattern in your interface, and walks through the design structure in detail.

screenshot of the task report pattern

Design structure

This page will break down this expression so you can better understand how to adapt this pattern to your own data so that it works to best suit your needs. For an example of how to modify this pattern or how to se a task report in a site, see the Task Report Tutorial.

The main components in this pattern are dropdowns, read only grids, process task links, and rich text. The image below displays how the pattern looks on a blank interface with callouts for the main components. You can examine the entire expression or jump down to the subsections below with referenced line numbers to see a detailed breakdown of the main components.

Pattern expression

When you drag and drop the Task Report pattern onto your interface, 160 lines of expressions will be added to the section where you dragged it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
a!localVariables(
  local!statusFilter: null,
  
  /* https://docs.appian.com/suite/help/latest/Task_Report_Tutorial.html */
  /* Basic steps to follow:                                              */
  /* 1. Create a Process Report object                                   */
  /* 2. Duplicate an existing process report, e.g. My Tasks              */
  /* 3. Create a Document constant for the report, e.g. MY_TASKS_REPORT  */
  /* 4. Replace local!taskReportData in this interface with a            */
  /*    process analytics query, e.g.                                    */
  /*    local!taskReportData: a!queryProcessAnalytics(                   */                      
  /*      report: cons!MY_TASKS_REPORT,                                  */
  /*      query: a!query(                                                */
  /*        pagingInfo: a!pagingInfo(                                    */
  /*          startIndex: 1,                                             */
  /*          batchSize: 10,                                             */
  /*          sort: a!sortInfo(                                          */
  /*            field: "c2",                                             */
  /*            ascending: true                                          */
  /*          )                                                          */
  /*       ),                                                            */
  /*       filter: a!queryFilter(                                        */
  /*         field: "c5",                                                */
  /*         operator: "in",                                             */
  /*         value: local!statusFilter,                                  */
  /*         applyWhen: a!isNotNullOrEmpty(local!statusFilter)           */
  /*       )                                                             */
  /*     )                                                               */
  /*   ),                                                                */                                                        
      
  /* Placeholder variable for the task data returned by a process analytics query */
  local!taskReportData: {
    startIndex: 1,
    batchSize: 7,
    sort: {field: "c2", ascending: false},
    totalCount: 10,
    data: a!localVariables(
      local!data: {
        a!map(c5: 0, c4: 1, c3: "New Purchase Request", c8: loggedInUser(), c7: null, c2: now(), c0: "Approve Purchase Request #38",  dp0: 268440077, dp2: null, dp4: null, dp3: 268435772, dp5: 268435772, dp7: null, dp8: null),
        a!map(c5: 0, c4: 1, c3: "New Purchase Request", c8: loggedInUser(), c7: null, c2: now(), c0: "Approve Purchase Request #39",  dp0: 268440067, dp2: null, dp4: null, dp3: 268435771, dp5: 268435771, dp7: null, dp8: null),
        a!map(c5: 0, c4: 1, c3: "Document Processing",  c8: loggedInUser(), c7: null, c2: now(), c0: "Review Document: Invoice #123", dp0: 268440067, dp2: null, dp4: null, dp3: 268435771, dp5: 268435771, dp7: null, dp8: null),
        a!map(c5: 0, c4: 1, c3: "New Purchase Request", c8: loggedInUser(), c7: null, c2: now(), c0: "Approve Purchase Request #40",  dp0: 268440067, dp2: null, dp4: null, dp3: 268435771, dp5: 268435771, dp7: null, dp8: null),
        a!map(c5: 1, c4: 1, c3: "Document Processing",  c8: loggedInUser(), c7: null, c2: now(), c0: "Review Document: Invoice #124", dp0: 268440067, dp2: null, dp4: null, dp3: 268435771, dp5: 268435771, dp7: null, dp8: null),
        a!map(c5: 1, c4: 1, c3: "Document Processing",  c8: loggedInUser(), c7: null, c2: now(), c0: "Review Document: Invoice #125", dp0: 268440067, dp2: null, dp4: null, dp3: 268435771, dp5: 268435771, dp7: null, dp8: null),
        a!map(c5: 1, c4: 1, c3: "New Purchase Request", c8: loggedInUser(), c7: null, c2: now(), c0: "Approve Purchase Request #41",  dp0: 268440067, dp2: null, dp4: null, dp3: 268435771, dp5: 268435771, dp7: null, dp8: null)
      },
      if(
        a!isNullOrEmpty(local!statusFilter),
        local!data,
        index(
          local!data,
          wherecontains(local!statusFilter, local!data.c5),
          {}
        )
      )
    ),
    identifiers: {123456781, 123456782, 123456783, 123456784, 123456785, 123456786, 123456787},
    name: "My Tasks",
    /* Maps field labels above to user friendly name */
    columnConfigs: {
      a!map(label: "Name",        field: "c0", drilldownField: "dp0", configuredFormatting: "NORMAL_TEXT", configuredDrilldown: "TASK_DETAILS"),
      a!map(label: "Process",     field: "c3", drilldownField: "dp3", configuredFormatting: "NORMAL_TEXT", configuredDrilldown: "PROCESS_DASHBOARD"),
      a!map(label: "Status",      field: "c5", drilldownField: "dp5", configuredFormatting: "TASK_STATUS", configuredDrilldown: "PROCESS_DETAILS"),
      a!map(label: "Received On", field: "c2", drilldownField: "dp2", configuredFormatting: "DATE_TIME",   configuredDrilldown: null)
    }
  },
  /* Maps the "c5" / "Status" field values to status names */
  local!taskStatuses: {
    a!map(name: "Assigned",               icon: "user-o",             color: "#666666"),
    a!map(name: "Accepted",               icon: "user-check",         color: "ACCENT"),
    a!map(name: "Completed",              icon: "check-circle",       color: "POSITIVE"),
    a!map(name: "Not Started",            icon: "circle-o-large",     color: "#666666"),
    a!map(name: "Cancelled",              icon: "stop-circle",        color: "#fdb858"),
    a!map(name: "Paused",                 icon: "pause-circle",       color: "#666666"),
    a!map(name: "Unattended",             icon: "question-circle",    color: "#666666"),
    a!map(name: "Aborted",                icon: "minus-circle",       color: "#fdb858"),
    a!map(name: "Cancelled By Exception", icon: "times-circle",       color: "NEGATIVE"),
    a!map(name: "Submitted",              icon: "share",              color: "ACCENT"),
    a!map(name: "Running",                icon: "spinner",            color: "ACCENT"),
    a!map(name: "Error",                  icon: "exclamation-circle", color: "NEGATIVE")
  },
  {
    a!sectionLayout(
      label: "My Tasks",
      labelColor: "SECONDARY",
      contents: {
        a!columnsLayout(
          columns: {
            a!columnLayout(
              contents: {
                a!multipleDropdownField(
                  label: "Status",
                  labelPosition: "COLLAPSED",
                  placeholder: "All statuses",
                  choiceLabels: { "Assigned", "Accepted", "Completed", "Not Started" },
                  choiceValues: enumerate(4),
                  value: local!statusFilter,
                  saveInto: local!statusFilter
                )
              },
              width: "MEDIUM"
            )
          },
          marginBelow: "NONE"
        ),
        a!gridField(
          label: "My Tasks",
          labelPosition: "COLLAPSED",
          data: local!taskReportData.data,
          columns: a!forEach(
            items: local!taskReportData.columnConfigs,
            expression: a!gridColumn(
              label: fv!item.label,
              sortField: fv!item.field,
              value: a!localVariables(
                local!fieldValue: index(fv!row, fv!item.field, {}),
                /* Display the data based on its configured formatting */
                a!match(
                  value: fv!item.configuredFormatting,
                  equals: "TASK_STATUS",
                  then: a!localVariables(
                    local!status: index(local!taskStatuses, local!fieldValue + 1, {}),
                    a!richTextDisplayField(
                      value: {
                        a!richTextIcon(
                          icon: index(local!status, "icon", "circle"),
                          color: index(local!status, "color", "#666666")
                        ),
                        "  ",
                        index(local!status, "name", "Other")
                      }
                    )
                  ),
                  equals: "DATE_TIME",
                  then: if(
                    a!isNullOrEmpty(local!fieldValue),
                    local!fieldValue,
                    text(local!fieldValue, "MMM D, YYYY, H:MM am/pm")
                  ),
                  /* Show a process link for task details */
                  whenTrue: fv!item.configuredDrilldown = "TASK_DETAILS",
                  then: a!linkField(
                    links: a!processTaskLink(
                      label: local!fieldValue,
                      task: index(fv!row, fv!item.drilldownField, {})
                    )
                  ),
                  default: local!fieldValue
                )
              ),
              align: if(fv!item.configuredFormatting = "DATE_TIME", "END", "START")
            )
          ),
          borderStyle: "LIGHT",
          rowHeader: 1
        )
      }
    )
  }
)

[Line 1-30] Provide instructions in comments

The first two lines in the expression begin the local variables, but are directly followed by 25 lines of comments. These comments contain a link to the Task Report Tutorial and a set of 4 steps to tell you how to create a task report.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
a!localVariables(
  local!statusFilter: null,
  
  /* https://docs.appian.com/suite/help/latest/Task_Report_Tutorial.html */
  /* Basic steps to follow:                                              */
  /* 1. Create a Process Report object                                   */
  /* 2. Duplicate an existing process report, e.g. My Tasks              */
  /* 3. Create a Document constant for the report, e.g. MY_TASKS_REPORT  */
  /* 4. Replace local!taskReportData in this interface with a            */
  /*    process analytics query, e.g.                                    */
  /*    local!taskReportData: a!queryProcessAnalytics(                   */                      
  /*      report: cons!MY_TASKS_REPORT,                                  */
  /*      query: a!query(                                                */
  /*        pagingInfo: a!pagingInfo(                                    */
  /*          startIndex: 1,                                             */
  /*          batchSize: 10,                                             */
  /*          sort: a!sortInfo(                                          */
  /*            field: "c2",                                             */
  /*            ascending: true                                          */
  /*          )                                                          */
  /*       ),                                                            */
  /*       filter: a!queryFilter(                                        */
  /*         field: "c5",                                                */
  /*         operator: "in",                                             */
  /*         value: local!statusFilter,                                  */
  /*         applyWhen: a!isNotNullOrEmpty(local!statusFilter)           */
  /*       )                                                             */
  /*     )                                                               */
  /*   ),                                                                */ 

[Line 31-66] Define the local variable for task data

This is the first local variable that populates the placeholder data for the grid.

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
  /* Placeholder variable for the task data returned by a process analytics query */
  local!taskReportData: {
    startIndex: 1,
    batchSize: 7,
    sort: {field: "c2", ascending: false},
    totalCount: 10,
    data: a!localVariables(
      local!data: {
        a!map(c5: 0, c4: 1, c3: "New Purchase Request", c8: loggedInUser(), c7: null, c2: now(), c0: "Approve Purchase Request #38",  dp0: 268440077, dp2: null, dp4: null, dp3: 268435772, dp5: 268435772, dp7: null, dp8: null),
        a!map(c5: 0, c4: 1, c3: "New Purchase Request", c8: loggedInUser(), c7: null, c2: now(), c0: "Approve Purchase Request #39",  dp0: 268440067, dp2: null, dp4: null, dp3: 268435771, dp5: 268435771, dp7: null, dp8: null),
        a!map(c5: 0, c4: 1, c3: "Document Processing",  c8: loggedInUser(), c7: null, c2: now(), c0: "Review Document: Invoice #123", dp0: 268440067, dp2: null, dp4: null, dp3: 268435771, dp5: 268435771, dp7: null, dp8: null),
        a!map(c5: 0, c4: 1, c3: "New Purchase Request", c8: loggedInUser(), c7: null, c2: now(), c0: "Approve Purchase Request #40",  dp0: 268440067, dp2: null, dp4: null, dp3: 268435771, dp5: 268435771, dp7: null, dp8: null),
        a!map(c5: 1, c4: 1, c3: "Document Processing",  c8: loggedInUser(), c7: null, c2: now(), c0: "Review Document: Invoice #124", dp0: 268440067, dp2: null, dp4: null, dp3: 268435771, dp5: 268435771, dp7: null, dp8: null),
        a!map(c5: 1, c4: 1, c3: "Document Processing",  c8: loggedInUser(), c7: null, c2: now(), c0: "Review Document: Invoice #125", dp0: 268440067, dp2: null, dp4: null, dp3: 268435771, dp5: 268435771, dp7: null, dp8: null),
        a!map(c5: 1, c4: 1, c3: "New Purchase Request", c8: loggedInUser(), c7: null, c2: now(), c0: "Approve Purchase Request #41",  dp0: 268440067, dp2: null, dp4: null, dp3: 268435771, dp5: 268435771, dp7: null, dp8: null)
      },
      if(
        a!isNullOrEmpty(local!statusFilter),
        local!data,
        index(
          local!data,
          wherecontains(local!statusFilter, local!data.c5),
          {}
        )
      )
    ),
    identifiers: {123456781, 123456782, 123456783, 123456784, 123456785, 123456786, 123456787},
    name: "My Tasks",
    /* Maps field labels above to user friendly name */
    columnConfigs: {
      a!map(label: "Name",        field: "c0", drilldownField: "dp0", configuredFormatting: "NORMAL_TEXT", configuredDrilldown: "TASK_DETAILS"),
      a!map(label: "Process",     field: "c3", drilldownField: "dp3", configuredFormatting: "NORMAL_TEXT", configuredDrilldown: "PROCESS_DASHBOARD"),
      a!map(label: "Status",      field: "c5", drilldownField: "dp5", configuredFormatting: "TASK_STATUS", configuredDrilldown: "PROCESS_DETAILS"),
      a!map(label: "Received On", field: "c2", drilldownField: "dp2", configuredFormatting: "DATE_TIME",   configuredDrilldown: null)
    }
  },

When you adapt this pattern to work for you, you need to remove this entire section (lines 31-66) and replace the pattern's placeholder data with your own data.

To replace the placeholder data:

  1. Copy and paste the following expression from the commented expression in lines 11-29 of the pattern and use it as the value for local!taskReportData on line 32:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
       local!taskReportData: a!queryProcessAnalytics(                                         
       report: cons!MY_TASKS_REPORT,                                  
       query: a!query(                                                
           pagingInfo: a!pagingInfo(                                    
             startIndex: 1,                                             
             batchSize: 10,                                             
             sort: a!sortInfo(                                          
               field: "c2",                                             
               ascending: true                                          
             )                                                          
           ),                                                            
           filter: a!queryFilter(                                        
              field: "c5",                                                
              operator: "in",                                             
              value: local!statusFilter,                                  
              applyWhen: a!isNotNullOrEmpty(local!statusFilter)           
            )                                                             
          )                                                               
       ),
    
  2. Replace cons!MY_TASKS_REPORT with the constant that points to your task report that you created in step 2 in the section above.
  3. To see your changes reflected in the interface preview, click TEST.

Clicking TEST forces the local variables in your interface preview to refresh. Do this any time you update a local variable to see your changes reflected in the interface.

To learn more about adapting this pattern to use your own data and reports, see the Task Report tutorial.

Reference task report columns

Notice in the new local variable expression that the field parameter values are c5 and c2. This comes from the underlying process report, which identifies each column with a field id.

You can see these field ids and which column they refer to in the LOCAL VARIABLES pane in the interface object. This pane displays the query results for the local!taskReportData variable. Simply expand taskReportData, then columnConfigs to see the column configuration parameters for each column in the task report.

These configurations list the label, field, drilldownField, configuredFormatting, and configuredDrilldown parameters for each column. Looking at this, we can see the field id c2 is for the "Received" column and c5 is for the "Status" column.

screenshot of the local variables pane to show the configurations associated with the task report columns

You can also use these parameters with fv!item within the a!forEach() function that creates the grid. For example, the pattern uses fv!item.label, fv!item.field, and fv!item.configuredFormatting for formatting the grid columns.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
...
a!gridField(
          label: "My Tasks",
          labelPosition: "COLLAPSED",
          data: local!taskReportData.data,
          columns: a!forEach(
            items: local!taskReportData.columnConfigs,
            expression: a!gridColumn(
!             label: fv!item.label,
!             sortField: fv!item.field,
              value: a!localVariables(
                local!fieldValue: index(fv!row, fv!item.field, {}),
                /* Display the data based on its configured formatting */
                a!match(
!                 value: fv!item.configuredFormatting,
                  equals: "TASK_STATUS",
                  then: a!localVariables(
                    local!status: index(local!taskStatuses, local!fieldValue + 1, {}),
                    a!richTextDisplayField(
                      value: {
                        a!richTextIcon(
                          icon: index(local!status, "icon", "circle"),
                          color: index(local!status, "color", "#666666")
                        ),
                        "  ",
                        index(local!status, "name", "Other")
                      }
                    )
                  ),
...

You can use this column configuration information to make changes to the task report. For example, you could sort the report by priority (c4) instead of the received date (c2).

[Line 67-81] Define the local variable to make friendly names for statuses

This section of the expression creates user-friendly names for each standard task status and maps it to an icon and color. When you adapt this pattern to work with your own data and tasks, you can use all or some of these task statuses, depending on which are most relevant for your workflow.

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
  /* Maps the "c5" / "Status" field values to status names */
  local!taskStatuses: {
    a!map(name: "Assigned",               icon: "user-o",             color: "#666666"),
    a!map(name: "Accepted",               icon: "user-check",         color: "ACCENT"),
    a!map(name: "Completed",              icon: "check-circle",       color: "POSITIVE"),
    a!map(name: "Not Started",            icon: "circle-o-large",     color: "#666666"),
    a!map(name: "Cancelled",              icon: "stop-circle",        color: "#fdb858"),
    a!map(name: "Paused",                 icon: "pause-circle",       color: "#666666"),
    a!map(name: "Unattended",             icon: "question-circle",    color: "#666666"),
    a!map(name: "Aborted",                icon: "minus-circle",       color: "#fdb858"),
    a!map(name: "Cancelled By Exception", icon: "times-circle",       color: "NEGATIVE"),
    a!map(name: "Submitted",              icon: "share",              color: "ACCENT"),
    a!map(name: "Running",                icon: "spinner",            color: "ACCENT"),
    a!map(name: "Error",                  icon: "exclamation-circle", color: "NEGATIVE")
  },

[Line 82-105] Create the status filter

This section of the expression creates the status filter using a multiple dropdown field. When you adapt this pattern to work with your own data and tasks, change the choice labels and values in the dropdown to match your statuses.

82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  {
    a!sectionLayout(
      label: "My Tasks",
      labelColor: "SECONDARY",
      contents: {
        a!columnsLayout(
          columns: {
            a!columnLayout(
              contents: {
                a!multipleDropdownField(
                  label: "Status",
                  labelPosition: "COLLAPSED",
                  placeholder: "All statuses",
                  choiceLabels: { "Assigned", "Accepted", "Completed", "Not Started" },
                  choiceValues: enumerate(4),
                  value: local!statusFilter,
                  saveInto: local!statusFilter
                )
              },
              width: "MEDIUM"
            )
          },
          marginBelow: "NONE"
        ),

[Line 106-160] Create the grid

This section of the expression creates the grid to display tasks, formats the status column, and adds process links to each task. The grid uses the a!forEach() function to loop through all the local variables associated with each placeholder task and display them as a row in the grid.

Lines 118-119 use the a!match() function to determine the type of data (either date, status, or text). The e.

Lines 120-133 use the then parameter in the match() function to format any values of type TASK_STATUS so that they show the status.

Lines 134-139 use the then parameter to format any values of type DATE_TIME so that they show when the task was received.

Lines 140-147 use the then parameter to format the process task links for each placeholder task in the grid so that users can select a task and view its details.

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
        a!gridField(
          label: "My Tasks",
          labelPosition: "COLLAPSED",
          data: local!taskReportData.data,
          columns: a!forEach(
            items: local!taskReportData.columnConfigs,
            expression: a!gridColumn(
              label: fv!item.label,
              sortField: fv!item.field,
              value: a!localVariables(
                local!fieldValue: index(fv!row, fv!item.field, {}),
                /* Display the data based on its configured formatting */
                a!match(
                  value: fv!item.configuredFormatting,
                  equals: "TASK_STATUS",
                  then: a!localVariables(
                    local!status: index(local!taskStatuses, local!fieldValue + 1, {}),
                    a!richTextDisplayField(
                      value: {
                        a!richTextIcon(
                          icon: index(local!status, "icon", "circle"),
                          color: index(local!status, "color", "#666666")
                        ),
                        "  ",
                        index(local!status, "name", "Other")
                      }
                    )
                  ),
                  equals: "DATE_TIME",
                  then: if(
                    a!isNullOrEmpty(local!fieldValue),
                    local!fieldValue,
                    text(local!fieldValue, "MMM D, YYYY, H:MM am/pm")
                  ),
                  /* Show a process link for task details */
                  whenTrue: fv!item.configuredDrilldown = "TASK_DETAILS",
                  then: a!linkField(
                    links: a!processTaskLink(
                      label: local!fieldValue,
                      task: index(fv!row, fv!item.drilldownField, {})
                    )
                  ),
                  default: local!fieldValue
                )
              ),
              align: if(fv!item.configuredFormatting = "DATE_TIME", "END", "START")
            )
          ),
          borderStyle: "LIGHT",
          rowHeader: 1
        )
      }
    )
  }
)
Open in Github Built: Wed, Dec 07, 2022 (10:13:16 PM)

On This Page

FEEDBACK