Task Report Tutorial

The walk-through on this page will help you create your first task report. Task reports display task information with a link for users to open each task and begin working on it.

When you save a Tempo report as a task report, it appears on the Tasks tab. Task reports are also used with sites.

For our example, we'll pull data from the My Tasks process report. We'll describe how to use the a!queryProcessAnalytics() system function to display data from the process report in a grid. Then, we'll show you how to create links to tasks and format the data so it looks more user-friendly. Finally, we'll show you how to add dynamic filters to your report.

Use the data provided to understand how the configurations work. Then, try it with your own data.

The content below assumes a basic familiarity with interfaces, specifically the Paging Grid and Dropdown components, and focuses more on the specifics of designing and creating a task report. Consider going through the SAIL and Grid Tutorials first and taking a look at the Tempo Report Design page before proceeding.

Create the Appian Tutorial Application

The Appian Tutorial application is used throughout Appian tutorials. If you have already created the tutorial application, skip the steps in this section.

To begin with, we need to create an application to contain our design objects.

We will be creating the Appian Tutorial application for this tutorial. All of Appian's tutorials use the Appian Tutorial application as the reference application. This means that, once you complete this tutorial, you can reuse this application as you work through the other tutorials.

To create the Appian Tutorial application:

  1. Log in to Appian Designer (for example, myappiansite.com/suite/design).
  2. Click NEW APPLICATION.
  3. In the Create New Application dialog, configure the following properties:

    Property Description
    Name Enter Appian Tutorial.
    Description Leave blank. It's normally a best practice to add descriptions to all design objects. However, to save a little time, we're skipping describing how to add descriptions during this tutorial.
    Application Prefix Retain the default prefix, AT, which Appian constructs using the initial characters of each word you entered in the Name parameter. We'll be following the recommended naming standard, and using this short unique prefix whenever we name an object in this application.
  4. Click CREATE.
  5. In the Review Application Security dialog, keep the default security for now. We'll set the long-term security after we create groups in this tutorial.

    The security of the application object is unrelated to the security of each of the objects contained within the application. This means that you will need to set security permissions for every object in an application in addition to the application object itself. For more information about security permissions for the application object, see Application Security.

  6. Click SAVE. The application view appears.

    screenshot of the application view

    Right now, the application is empty. Each design object that you create during the course of this tutorial will appear in this list and automatically be associated with the tutorial application.

Add groups to the application

If you created the Appian Tutorial application in a previous tutorial, skip the steps in this section.

One of the first things that you need to do for each new application is to create at least two groups: one for the users of the application and one for the application's administrators. Groups are important building blocks of an application, because they allow you to organize users and assign permissions to the groups of users as you add objects.

Let's create two groups for this application so that we can add security as we go along:

  • AT Administrators
  • AT Users

To create these groups:

  1. In the application view, click NEW > Group.
  2. In the Create Group dialog, configure the following properties:
    • For Name, enter AT Administrators.
    • For Group Members, enter your username. We're adding you to these groups so you'll have permissions to create and modify objects in this tutorial.
  3. Leave all other default settings.
  4. Click CREATE.
  5. In the Review Group Security dialog, give yourself permissions to view and edit the group:
    • Click Add Users or Groups.
    • For Users or Groups, enter your username.
    • For Permission Level, leave the default Administrator value.
    • Click SAVE.
  6. Repeat these steps, using AT Users as the Name value.

screenshot of the application view containing two groups

Learn more about managing groups and users on the Group Management page.

Add security to the application

If you created the Appian Tutorial application in a previous tutorial, skip the steps in this section.

We should address the security of the application before we move on. At the beginning of this tutorial, you assigned yourself specific permissions to the application. However, Appian recommends configuring security using groups, rather than individuals for better maintainability.

Now that we've created the groups we need, we'll grant the following security permissions:

Group Permissions Result
AT Users Viewer Members of this group can see the application.
AT Administrators Administrator Members of this group are administrators of the application.

To add security to the application:

  1. In the application view, open the settings menu , then click Application Security. screenshot of the application view and settings menu, focused on the Application Security button
  2. In the Application Security dialog, set the Default (All Other Users) permissions to No Access.
  3. Click Add User or Group, then add permissions for the groups as described in the table above.
  4. Click delete icon next to your individual permissions to remove them.
  5. Click SAVE CHANGES. screenshot of the application security dialog

Create a Constant for the My Tasks Process Report

Before we create the task report interface, we need to create a constant for the My Tasks process report. This constant will be used in the interface that we will create in the next step.

  1. Navigate to the application contents view of the Appian Tutorial application (if needed).
  2. From the New menu, click Constant. This will open the Create Constant form.
  3. Leave Create from Scratch selected.
  4. Enter AT_MY_TASKS_REPORT in the Name field.
  5. Select Document from the Data Type dropdown.
  6. Enter My Tasks in the Value field and select the document that is suggested. If no suggestions appear for My Tasks, search for and use active_tasks instead.
  7. Enter Examples in the Save In field and select the folder that is suggested.
  8. Click Create.

Create an Interface for the Task Report

Now we will create an interface to be used to display the task report data in a grid. We will use a!queryProcessAnalytics() system function to populate a Paging Grid component with data from the My Tasks process report and create a Tempo task report out of it.

Note that while we are using a built-in report for this example, any process report can potentially be queried.

  1. Navigate to the application contents view of the Appian Tutorial application (if needed).
  2. From the New menu, click Interface. This will open the Create Interface form.
  3. Leave Create from Scratch selected
  4. Enter AT_myTasksReport in the Name field.
  5. Enter Examples in the Save In field and select the folder that is suggested.
  6. Click Create & Edit.

The newly created interface will open in a new tab by default. If you don't see a new tab, check your browser to see if you have pop-ups enabled.

Switch to the Expression Mode using the toggle in the header or by the keyboard shortcut (Ctrl + M).

Now enter the following expression:

1
2
3
4
5
6
a!localVariables(
  local!report: a!queryProcessAnalytics(
    report: cons!AT_MY_TASKS_REPORT
  ),
  a!textField(readOnly: true, value: local!report)
)

The interface's text field will show the text representation of the process report data. You will see something similar to the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[
  startIndex=1,
  batchSize=25,
  sort=[field=c2, ascending=false],
  totalCount=66,
  data=
    [c5:0,c4:1,c3:New PR: Purchase Request Number 68,c8:[Group:6]; [Group:7]; [Group:3],c7:,c2:12/19/2014 2:23 PM GMT+00:00,c0:Review Purchase Request: Purchase Request Number 68,dp0:268440077,dp2:,dp4:,dp3:268435772,dp5:268435772,dp7:,dp8:];
    [c5:0,c4:1,c3:New PR: Purchase Request Number 43,c8:[Group:6],c7:,c2:12/19/2014 2:23 PM GMT+00:00,c0:Approve Purchase Request: Purchase Request Number 43,dp0:268440067,dp2:,dp4:,dp3:268435771,dp5:268435771,dp7:,dp8:],
  identifiers=268440077; 268440067
  name=My Tasks
  description=A list of all tasks for the current user.
  columnConfigs=
    [label:Name,field:c0,drilldownField:dp0,configuredFormatting:NORMAL_TEXT,configuredDrilldown:TASK_DETAILS];
    [label:Received,field:c2,drilldownField:dp2,configuredFormatting:DATE_TIME,configuredDrilldown:];
    [label:Priority,field:c4,drilldownField:dp4,configuredFormatting:PRIORITY_ICON,configuredDrilldown:];
    [label:Process,field:c3,drilldownField:dp3,configuredFormatting:NORMAL_TEXT,configuredDrilldown:PROCESS_DASHBOARD];
    [label:Status,field:c5,drilldownField:dp5,configuredFormatting:TASK_STATUS,configuredDrilldown:PROCESS_DETAILS];
    [label:Deadline,field:c7,drilldownField:dp7,configuredFormatting:DATE_TIME,configuredDrilldown:];
    [label:Assigned To,field:c8,drilldownField:dp8,configuredFormatting:USER_OR_GROUP_NAME,configuredDrilldown:],
  errorMessage=
]

Notice that rows are returned in the data array with each column's cell being represented by a key/value pair. Details about each column, including the key to access that column's data from the data array, are provided in the columnConfigs field.

Let's try displaying the data using a grid instead of a single text field. For this example, we'll take the columns labeled Name, Process, and Status. To begin, you don't need to use local variables. Insert the query directly into the data parameter of the grid component:

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!gridField(
    label: "My Tasks",
    instructions: "A list of all tasks for the current user",
    labelPosition: "ABOVE",
    data: a!queryProcessAnalytics(
      report: cons!AT_MY_TASKS_REPORT,
      query: a!query(
        pagingInfo: fv!pagingInfo
      )
    ),
    columns: {
      a!gridColumn(
        label: "Name",
        sortField: "c0",
        value: fv!row.c0
      ),
      a!gridColumn(
        label: "Process",
        sortField: "c3",
        value: fv!row.c3
      ),
      a!gridColumn(
        label: "Status",
        sortField: "c5",
        value: fv!row.c5
      ),
    },
    rowHeader: 1
  )

You should see an interface similar to the following (it will vary based on your personal task list):

Before moving on, however, let's save the interface by clicking Save. Keep this window open so you can quickly modify the interface as we continue.

Create and View the Task Report

Now let's save the interface as a task report and view it in Tempo.

  1. From the settings menu (gear icon), click Save as…. This will display the Save Interface As form.
  2. Enter My Tasks in the Report Name field.
  3. Select the Save as Task Report checkbox.
  4. Confirm that the Application field has the value Application Tutorial in it.
  5. Click Save.

Now if you visit the Tasks tab in Tempo, you will see a link for the My Tasks report below the default filters.

Display Tasks with Multiple Assignees

In Appian, tasks can be assigned to multiple people and to groups. If your tasks are assigned to other users too, you may want to see these other assignees in your task list. We need to add a new column to the grid to show this information. To show all of the items in the array, we need to use the looping function a!forEach. The function will go through each item in the array and return the information we're looking for. In this example, that is the user's first and last name. To format the information, we use the concat() function and char(10) to have each item appear on its own line.

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
  a!gridField(
    label: "My Tasks",
    instructions: "A list of all tasks for the current user",
    labelPosition: "ABOVE",
    data: a!queryProcessAnalytics(
      report: cons!AT_MY_TASKS_REPORT,
      query: a!query(
        pagingInfo: fv!pagingInfo
      )
    ),
    columns: {
      a!gridColumn(
        label: "Name",
        sortField: "c0",
        value: fv!row.c0
      ),
      a!gridColumn(
        label: "Process",
        sortField: "c3",
        value: fv!row.c3
      ),
      a!gridColumn(
        label: "Status",
        sortField: "c5",
        value: fv!row.c5
      ),
!     a!gridColumn(
!       label: "Assignee",
!       sortField: "c8",
!       value: concat(
!         a!forEach(
!           items: fv!row.c8,
!           expression: if(
!             runtimetypeof(fv!item) = 4,
!             /*User is type 4; group is type 5*/
!             user(fv!item, "firstName") & " " & user(fv!item, "lastName") & char(10),
!             /*Adding char(10) adds line breaks to the list of names*/
!             group(fv!item, "groupName")
!            )
!         )
!       )
!     )
    },
    rowHeader: 1
  )

Unlike the process report, the grid we just created only displays the task name. Users have no way to open the task. What we want to do is link the Name column to the task, but the other columns should remain unlinked.

We can do this by updating the column expression with the following definition:

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
a!gridField(
  label: "My Tasks",
  instructions: "A list of all tasks for the current user",
  labelPosition: "ABOVE",
  data: a!queryProcessAnalytics(
    report: cons!AT_MY_TASKS_REPORT,
    query: a!query(
      pagingInfo: fv!pagingInfo
    )
  ),
  columns: {
    a!gridColumn(
      label: "Name",
      sortField: "c0",
!     value: a!linkField(
!       links: a!processTaskLink(
!         label: fv!row.c0,
!         task: fv!identifier
!       )
!     )
    ),
    a!gridColumn(
      label: "Process",
      sortField: "c3",
      value: fv!row.c3
    ),
    a!gridColumn(
      label: "Status",
      sortField: "c5",
      value: fv!row.c5
    ),
  },
  rowHeader: 1
)

Now if you return to your AT_myTasksReport interface, the tasks should be linked. We are now using a!processTaskLink() to create a link for each data point in the column. We set the task property as fv!identifier to designate the task as the link destination. Label is set to fv!row.c0 to show the task's name as the link text.

See also: Process Task Link

Format the Status Column

You may have noticed that the Status column returned numbers instead of the text you normally see in the Portal task report. This is because process reports auto-format some columns, including task status, task priority, users, dates, and more, but we are telling our grid to display every column as text.

We can apply one or more of these formats by using a!forEach() to call a formatting expression if the report column is configured with a relevant formatting type.

This expression uses the task status number as an index into a set of status names. Note that because each data row is a Dictionary that maps keys to values of Any Type, tointeger must be used to convert the cell value from Any Type to Number (Integer).

To store the readable values for each status, we create a local variable local!taskStatuses.

Now we can update the AT_myTasksReport interface rule with the following definition:

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
! a!localVariables(
!  local!taskStatuses: {
!   "Assigned",
!   "Accepted",
!   "Completed",
!   "Not Started",
!   "Cancelled",
!   "Paused",
!   "Unattended",
!   "Aborted",
!   "Cancelled By Exception",
!   "Submitted",
!   "Running",
!   "Error",
!   "Other",
!   "Other",
!   "Skipped"
! },
      a!gridField(
        label: "My Tasks",
        instructions: "A list of all tasks for the current user",
        labelPosition: "ABOVE",
        data: a!queryProcessAnalytics(
          report: cons!AT_MY_TASKS_REPORT,
          query: a!query(
            pagingInfo: fv!pagingInfo
          )
        ),
        columns: {
          a!gridColumn(
            label: "Name",
            sortField: "c0",
            value: a!linkField(
              links: a!processTaskLink(
                label: fv!row.c0,
                task: fv!identifier
              )
            )
          ),
          a!gridColumn(
            label: "Process",
            sortField: "c3",
            value: fv!row.c3
          ),
          a!gridColumn(
            label: "Status",
            sortField: "c5",
!           value: if(
!             not(isnull(fv!row.c5)),
!             index(
!               local!taskStatuses,tointeger(fv!row.c5)+1,"Other"
!             ),
!             "Other"
!           )
!         ),
        },
        rowHeader: 1
      )
! )

Now instead of numbers in the status column, there are words like Assigned and Completed. For an example that uses an image column to display an icon for process statuses, see the Display Processes by Process Model with Status Icons Interface Recipe.

Add a Predefined Filter

With process reports, Appian lets users add their own filters to those configured in the report. For task reports, we can add extra filters via the query parameter of a!queryProcessAnalytics(). Then we can connect them to another component so users can use that component to change the filter on the report.

For our example, let's add a Dropdown component so users can filter the tasks by the most common statuses. To show the dropdown component above the grid, we need to also add a section layout to our interface.

Modify the AT_myTasksReport interface with the following:

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
a!localVariables(
! local!statusFilter: null,
  local!taskStatuses: {
    "Assigned",
    "Accepted",
    "Completed",
    "Not Started",
    "Cancelled",
    "Paused",
    "Unattended",
    "Aborted",
    "Cancelled By Exception",
    "Submitted",
    "Running",
    "Error",
    "Other",
    "Other",
    "Skipped"
  },
! a!sectionLayout(
!   contents:{
!     a!dropdownField(
!       label: "Status",
!       placeholder: "Pick a status",
!       choiceLabels: { "Assigned", "Accepted", "Completed", "Not Started" },
!       choiceValues: enumerate(4),
!       value: local!statusFilter,
!       saveInto: local!statusFilter
!     ),
      a!gridField(
        label: "My Tasks",
        instructions: "A list of all tasks for the current user",
        labelPosition: "ABOVE",
        data: a!queryProcessAnalytics(
          report: cons!AT_MY_TASKS_REPORT,
          query: a!query(
            pagingInfo: fv!pagingInfo,
!           filter: a!queryFilter(
!               field: "c5",
!               operator: "=",
!               value: local!statusFilter,
!               applyWhen: not(
                  isnull(
                    local!statusFilter
                  )
                ),
!             ),
          ),
        ),
        columns: {
          a!gridColumn(
            label: "Name",
            sortField: "c0",
            value: a!linkField(
              links: a!processTaskLink(
                label: fv!row.c0,
                task: fv!identifier
              )
            )
          ),
          a!gridColumn(
            label: "Process",
            sortField: "c3",
            value: fv!row.c3
          ),
          a!gridColumn(
            label: "Status",
            sortField: "c5",
            value: a!forEach(
              items: fv!row.c5,
              expression: if(
                not(isnull(fv!row.c5)),
                fn!index(
                  local!taskStatuses,tointeger(fv!item)+1,"Other"
                ),
                tostring(fv!item)
              )
            )
          )
        },
        rowHeader: 1
      )
!   }
! )
)

In this expression, we pass a filter to a!queryProcessAnalytics() that uses a statusFilter local variable as its value. That variable is set by the Dropdown component, where the task statuses are passed as choiceLabels and the corresponding numeric values are passed as choiceValues. Because the numeric values of these specific statuses are 0, 1, 2, and 3, we can use the enumerate() function to return those values. In the example above, we don't set a default value. Instead, you see all tasks in the grid and "Pick a status" as the placeholder in the dropdown filter. The local variable storing the selection is empty.

When you select Assigned, the value of the filter is to 0 which corresponds to the value of Assigned and only the tasks with that status are returned. If you select a different value from the dropdown, the grid updates to display only tasks that correspond to the selected status.

Click Save. Now go back to Tempo, and see that the filtered task list interface is now available.

Open in Github Built: Fri, Oct 22, 2021 (11:11:24 AM)

On This Page

FEEDBACK