Targetprocess

The Targetprocess Developer Hub

Welcome to the Targetprocess developer hub. Here you'll find comprehensive guides and documentation to help you start working with Targetprocess as quickly as possible and support you if you get stuck. Let's jump right in!

Docs

Configurable Dropdown

1. GENERAL DESCRIPTION

The Administrator can create UI elements of the “Dropdown” type with custom behavior, and add them to views. The customization consists in that the Administrator can define, in the form of an API v2 request, the rule by which the Dropdown generates the list of values that it shows when the User clicks on it.

The typical use case of the Configurable Dropdown is having a “dependent selector”. This means having a Dropdown which shows a limited list of the respective field’s values, depending on values set for other fields of the same entity. This prevents the User from having to scroll through a long list of all possible values.

Example 1: When the User is linking a Feature to a Program Increment (PI), they want the “Program Increment” Dropdown to list only the PIs of the particular Agile Release Train (ART) assigned to this Feature. The User doesn’t want to scroll through, and guess among, all the ARTs’ PIs.

Example 2: When the User is linking a work item to a Key Result, they want the “Key Result” Dropdown to list only the Key Results of the Objective this work item is linked to. The User doesn’t want to scroll through all the Key Results in the System.

2. HOW TO CONFIGURE AND ADD DROPDOWNS

2.1. What Is a Configuration?

A single particular case of customization of the Dropdown’s behavior is called a “Configuration” of the Dropdown. The Configurable Dropdown currently supports, and its any Configuration can be used in:

  1. Detailed views, as a Dropdown control element,
  2. List views and Inner Lists, as a unit.

Every Configuration can be associated with only one field of an Entity type (types). This field can be a link to a default (native domain) Entity or a link to an Extendable Domain Entity.

A Configuration is in fact a piece of code, a request to the Configurable Controls API which contains a set of attributes. The attributes are explained in the Configuration Attributes section.

2.2. Creating a Dropdown Configuration

A Configuration can be created with a mashup.
Let us create a sample Configuration to solve the problem from Example 1, above.

With the SAFe data model, our Account has, among other things, the following entity types:

  1. Agile Release Train, or ART. This is basically a “team of teams”. It is implemented as an Extendable Domain entity type and is parent to the Team entity type.
  2. Program Increment, or PI. This is basically an iteration of an ART’s work, i.e. a time period linked to an ART. It is a renamed Release, which is a default entity type.

By default, the “Program Increment” Dropdown shows a list of PIs of all the ARTs present in the Account, even if a particular ART has been assigned to the entity in question. It can be difficult for the User to scan through all the PIs most of which are irrelevant. This screenshot illustrates the problem:

PIs of all ARTs are available in the Program Increment Dropdown (Detailed view).PIs of all ARTs are available in the Program Increment Dropdown (Detailed view).

PIs of all ARTs are available in the Program Increment Dropdown (Detailed view).

PIs of all ARTs are available in the Program Increment Dropdown (List view).PIs of all ARTs are available in the Program Increment Dropdown (List view).

PIs of all ARTs are available in the Program Increment Dropdown (List view).

Now let’s add a mashup with a Configuration which alleviates the problem – see the code below. This Configuration makes the Dropdown of the “Program Increment” field show only the Program Increments of the ART which is assigned to this particular entity (e.g. Feature). In other words, it prevents the User from having to select from the PIs of all the ARTs in the Account.

This Configuration also sorts the list of PIs in the Dropdown by name in descending order. Given the naming conventions of this particular demo Account, this means that the newest PIs will appear at the top of the Dropdown’s list.

Sample code:

tau.mashups
    .addDependency('tau/api/configurable-controls/controls/v1')
    .addMashup(( controlsApiV1 ) => {
        controlsApiV1.addConfiguration('dropdown', {
          id: 'dd_conf_01',
          name: 'Program Increments of the assigned ART',
          label: 'Program Increment',
          supportedEntityTypes: ['userstory', 'feature'],
          requiredEntityFields: ['id', 'name', 'release'],
          sampleData: {
            release: { name: 'Program Increment' }
          },
          entityClickBehavior: 'openEntity',
          field: 'release',
          dropdownItemsSource: {
            type: 'interpolatedQuery',
            query: "release?where=(agileReleaseTrain.id==${{agileReleaseTrain.id}}$)&orderBy=name desc"
          }
        })
    })

When setting up the mashup, in the “Placeholder(s)” field you can use any global placeholder, e.g. footerPlaceholder.

After the mashup has been added, you can use this Configuration of the Dropdown in views. Note that you can add any number of Configurations in a single mashup.

(To learn more about how this mashup works, refer to the Configuration Attributes section.)

2.3. Adding a Dropdown Configuration to Detailed Views

On the Detailed view layout editor page, you can find a snippet of the necessary Configuration for use in your layout:

The list of Dropdown Configurations can be accessed in the layout editor.The list of Dropdown Configurations can be accessed in the layout editor.

The list of Dropdown Configurations can be accessed in the layout editor.

The snippet should be added as a new property component, or placed instead of an existing property component, in the target entity type’s Detailed view layout:

Substituting a default property component with a custom Dropdown Configuration in Detailed views.Substituting a default property component with a custom Dropdown Configuration in Detailed views.

Substituting a default property component with a custom Dropdown Configuration in Detailed views.

Now in Detailed views, our example Program Increment Dropdown only shows the PIs of the ART which is assigned to the entity:

Only the PIs of the selected ART are available in the Dropdown (Detailed view).Only the PIs of the selected ART are available in the Dropdown (Detailed view).

Only the PIs of the selected ART are available in the Dropdown (Detailed view).

2.4. Adding a Dropdown Configuration to a List View

In List views, the Configuration of the Dropdown is reflected in a custom Unit for the target field. Add this custom Unit to the view setup at the “Customize Cards” tab (you’ll probably want to substitute the default unit):

Changing the default “Program Increment” unit to a configured one in a List view.Changing the default “Program Increment” unit to a configured one in a List view.

Changing the default “Program Increment” unit to a configured one in a List view.

Now in this List view, the example Program Increment Dropdown only shows the PIs of the ART which is assigned to this particular entity:

Only the PIs of the selected ART are available in the Dropdown (List view).Only the PIs of the selected ART are available in the Dropdown (List view).

Only the PIs of the selected ART are available in the Dropdown (List view).


3. CONFIGURATION ATTRIBUTES

All the possible attributes of a Configuration of a Dropdown are listed and explained below.

3.1. id

Required? Yes.
Text ID specified by the mashup creator. Must be unique among controls of the same type (i.e. “dropdown”).

3.2. name

Required? No.
Friendly text name. Use this to help people understand what this Configuration does.

3.3. label

Required? Yes.
Text rendered as the Dropdown’s label in Detailed views, and as a column header in Lists.

3.4. supportedEntityTypes

Required? No.
Targetprocess entity type names (in lowercase) that support rendering this particular control. If none are provided, the control is considered to be universal.
Example snippet:
supportedEntityTypes: ['userstory', 'bug']

3.5. allowedLocations

Required? No.
Allows to use this Dropdown Configuration in specific view types only, e.g. only Detailed views but not Lists.
Example snippet:

allowedLocations: {
  listUnit: false,
  detailedView: true
}

By default a Configuration can be used in all view types currently supported by the Configurable Dropdown.

3.6. requiredEntityFields

Required? No.
A list of fields that should be available in “ConfigurableControlInfo” (see below) and must be requested for this control to render. The fields can belong to the very entity this Dropdown Configuration will be used with (the “target” entity), as well as to entities linked to it.

The fields are aggregated into a single API v2 selector, so it's possible to use field names (i.e. "effort") or aliased API v2 selectors (e.g. "userStoryId:userStory.id" – an ID of a User Story linked to the target entity).
Example snippet:

requiredEntityFields: [
    'id', 
    'name', 
   'feature:{id:feature.id,name:feature.name,projectId:feature.project.id}', 
    'tasks:tasks.select({id,name})
]

3.7. sampleData

Required? No.
A list of dummy values for all fields that are required by the "Required Entity Fields" attribute. These dummy values will be used to render the control in all editors (like Customize Cards) where entity data isn't available, to show a meaningful preview.
Example snippet:

sampleData: {
  id: 5,
  name: 'Some name',
  feature: {id: 10, name: 'Some feature name', projectId: 50},
  tasks: [
    {id: 18, name: 'Task 1'},
    {id: 19, name: 'Task 2'}
  ]
}

3.8. isEnabled

Required? No.
A callback that consists in a particular check to determine if the control must be enabled or disabled (i.e. read only).
Template:

isEnabled?: {
    callback: (info: ConfigurableControlInfo) => boolean | PromiseLike<boolean>;
    rerunOnRequiredFieldsChanged: string[];
  }

Example snippet 1 – the control is only enabled if the target entity’s name starts with an 'S' or 's':

isEnabled: {
    callback: info => info.entity.name.toLowerCase().startsWith('s'),
    rerunOnRequiredFieldsChanged: ['name']
}

Example snippet 2 – the control is always disabled (read only):

isEnabled: { 
    callback: () => false, 
    rerunOnRequiredFieldsChanged: [] 
}

The callback is executed a) prior to the control’s initialization, and b) when one of the entity’s fields listed in "rerunOnRequiredFieldsChanged" is updated.

On initial render, if the callback returns a promise-like, the control will be disabled and will remain disabled until the promise-like resolves with a truthy value; if it rejects or resolves with a falsy value, the control will remain disabled.

On a re-render of the Dropdown, the "rerunOnRequiredFieldsChanged" collection will be checked against the fields that are present in "requiredEntityFields" and have been updated. If any of them has been modified, the callback is executed.
If the callback returns a promise-like, for UX reasons, the control retains its previous "disabledness" visually (but not functionally) until the promise-like resolves, to prevent flashing on every modification.

NOTE that when registering the control as a unit (i.e. in Lists), this callback will be executed for every visible card. So if the callback performs some heavy and/or asynchronous work to verify visibility (like a network request), this may negatively affect performance when used as a unit.

If "rerunOnRequiredFieldsChanged" is not provided or empty, the callback will only be executed for the initial render.

If isEnabled is not provided, the control is always enabled.

3.9. entityClickBehavior

Required? Yes.
Determines what happens when the Dropdown is not open and the user clicks on the name of the entity selected for this field. "openDropdown" ignores the entity link and opens the Dropdown; "openEntity" opens the entity’s Detailed view.
Example snippet:
entityClickBehavior: 'openEntity'

3.10. field

Required? Yes.
The name of the entity’s field for which the Dropdown is to be used. Should be present in requiredEntityFields.

3.11. allowReset

Required? No.
A boolean attribute that determines whether the Dropdown supports an empty value. Is “true” by default.

3.12. dropdownItemsSource

Required? Yes.
A subset of attributes that determines where the items in the Dropdown’s list come from. The items can be provided either by an interpolated query or by a custom function.
Template:

dropdownItemsSource:
    | {
        type: 'interpolatedQuery';
        query: string;
      }
    | {
        type: 'custom';
        getItems: (info: ConfigurableControlInfo) => PromiseLike<{id: any; name: string}[]>;
      };

An interpolated query is a templated request to API v2. It can reference the target entity’s fields with template syntax: ${{}}$ (dollar sign, double open curly braces, expression, double closed curly braces, dollar sign), for example:
"feature?where=(epic.id=='${{epic.id}}$)"
Which means “show the Features that are linked to the same Epic this target entity is linked to”.

In the case of the type: 'custom' option, list items are provided by a custom function which takes the info about the Dropdown’s state (including the requiredEntityFields values) as input, and asynchronously returns an array of objects with 'id' and 'name' fields. In principle, this custom function can make requests to any destination or even return some hardcoded data.
Example:

getItems: async info => {
  const response = await fetch(`https://my-service.com/api/getPossibleProjects?id=${info.entity.id}`);
  const items = await response.json();
  return items;
}

This custom function makes a request to a particular service for an array of entities that satisfy a particular condition, then returns the array.

4. CONFIGURATIONS LIBRARY

This section is an aggregation of useful Dropdown Configuration examples from real Customer Accounts. You can take these examples and modify them to create your new Configurations.

As new useful examples are available, they will be added here.

4.1. Show Value Streams Relevant for the Assigned ARTs

With this Configuration, the Value Stream Dropdown will only show Value Streams relevant for the ARTs assigned to the target entity. If no ARTs are assigned, then the Dropdown shows all the Value Streams in the Account.

tau.mashups
    .addDependency('tau/api/configurable-controls/controls/v1')
    .addMashup(controlsApiV1 => {
        controlsApiV1.addConfiguration('dropdown', {
            id: 'feature_valuestream_filtered_by_assigned_art',
            name: 'Value Stream filtered by ART',
            label: 'Value Stream',
            supportedEntityTypes: ['feature'],
            requiredEntityFields: ['valueStream'],
            sampleData: {
                valueStream: { resourceType: 'valuestream', name: 'Value Stream' }
            },
            entityClickBehavior: 'openDropdown',
            field: 'valueStream',
            dropdownItemsSource: {
                type: 'interpolatedQuery',
                query: "valuestream?where=(valueStreamAgileReleaseTrains.count(${{agileReleaseTrain.id}}$ == null or agileReleaseTrain.id == ${{agileReleaseTrain.id}}$) > 0)&take=999"
            }
        })
    })

4.2. Show Program Increments with Their Corresponding Projects

With this Configuration, the Program Increment (or Release) Dropdown will show its list of possible values, each of them combined with the name of its corresponding Project entity. This is implemented with a custom items source, as an interpolated query won’t work.

Note that the list will only contain the currently running Program Increments (via the &where=(IsCurrent == True) condition).

The Dropdown lists PIs with the names of their corresponding Projects.The Dropdown lists PIs with the names of their corresponding Projects.

The Dropdown lists PIs with the names of their corresponding Projects.

tau.mashups
    .addDependency('tau/api/configurable-controls/controls/v1')
    .addDependency('tau/configurator')
    .addMashup(( controlsApiV1, configurator ) => {
        const store2 = configurator.getStore2();
        controlsApiV1.addConfiguration('dropdown', {
          id: 'dd_conf_03',
          name: 'PI with Project',
          label: 'PI w/ Project',
          supportedEntityTypes: ['teamiteration'],
          requiredEntityFields: ['release'],
          sampleData: {
            release: {name: 'Program Increment', resourceType: 'release'}
          },
          entityClickBehavior: 'openEntity',
          field: 'release',
          dropdownItemsSource: {
            type: 'custom',
            getItems: async () => {
                const releasesWithProjects = await store2.findAll('release?select={id,name,projectName:project.name}&where=(IsCurrent == True)&orderBy=name desc');
                return releasesWithProjects.map(release => ({
                    id: release.id,
                    name: `${release.name} (${release.projectName})`
                }));
            }
          }
        });
    })

Updated 24 days ago

Configurable Dropdown


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.