Setting up portfolioAssignments

portfolioAssignments is a dynamic component that can be used to display multiple groupings of entities that supports optional readonly mode and advanced filterings between several groupings.

Default behavior

By default, portfolioAssignments uses one of 3 preconfigured setups depending on which entities are configured on the account, for 4 entity types. It displays groupings of Teams, Teams+Agile Release Trains, or Teams+Agile Release Trains+Solution Trains on detailed views for User Stories, Features, Epics and Portfolio Epics (or whichever terms are used to denote them).

Default behavior - Teams only

When Agile Release Trains and Solution Trains are not enabled for account, portfolioAssignments only displays Team assignment:

576576

This configuration is equivalent to using property.teams component instead of portfolioAssignments.

Default behavior - Teams+Agile Release Trains

When Agile Release Trains are enabled but Solution Trains are not enabled, portfolioAssignments displays Team assignment and Agile Release Train assignment:

582582

Note that "Squads" is a term for "Teams" here.

🚧

Note that portfolioAssignments only checks that "Agile Release Train" entity is enabled on account. If it is detected, it assumes that all the necessary connections between work items (Portfolio Epics, Epics, Features and User Stories) and Agile Release Trains are also enabled. If that is not the case and you are using a non-standard entity configuration, please consider using property.teams instead, or applying a custom configuration.

In this configuration:

  • User Stories display Agile Release Train from their Feature in read-only mode
  • Features can only be assigned to a single Agile Release Train
  • Epics and Portfolio Epics can be assignled to multiple Agile Release Trains

When Agile Release Train is assigned to the entity (in editable or readonly mode), Teams selector filters available Teams to only include Teams that are assigned to the same Agile Release Train. For example, if Team A is assigned to ART1, Team B is assigned to ART2 and Team C is assigned to ART1, when you assign a Feature to ART1, Teams selector will only allow assigning Team A and Team C.

When you select a team with no Agile Release Train assigned, it will be automatically updated to match Agile Release Train of selected Team. For example, if in previous example work item entity has no Agile Release Train, when Team A is assigned, ART1 will be also automatically assigned to it.

Default behavior - Teams+Agile Release Trains+Solution Trains

When Solution Trains are enabled, portfolioAssignments displays Team assignment, Agile Release Train assignment and Solution Train assignment:

580580

In this configuration:

  • User Stories display Agile Release Train from their Feature in read-only mode
  • User Stories display Solution Train from their Feature's Epic in read-only mode
  • Features can be assigned to a single Agile Release Train
  • Features display Solution Train from their Epic in read-only mode
  • Epics can be assignled to multiple Agile Release Trains
  • Epics can be assigned to a single Solution Train
  • Portfolio Epics can be assigned to multiple Agile Release Trains
  • Portfolio Epics can be assigned to multiple Solution Trains

All the filtering and auto-assignment logic also applies:

  • When Solution Train is assigned, only ARTs from this Solution Train can be assigned, and only Teams from this Solution Train's ARTs can be assigned;
  • When ART is assigned, only Teams from this ART can be assigned;
  • When no Solution Train is assigned, assigning a work item to an ART automatically assigns it to this ART's Solution Train;
  • When no ART is assigned, assigning a work item to a Team automatically assigns it to this Team's ART (this can also trigger the above update and automatically assign this ART's Solution Train, if it's not assigned)

Customizing portfolioAssignments

Default entity configurations can also be configured to support arbitary entity type, connections, connection multiplicity, auto-assignment or filtering rules. To customize the logic of portfolioAssignments, it is possible to specify schemaConfig property with entityListMetadata and selectorConfig sub-properties.

entityListMetadata

This property configures which entity types are supported by the control, and how the list of entities is filtered when "plus" button is clicked. For example, consider default entityListMetadata for Teams+Agile Release Train configuration:

{
   "agileReleaseTrains":{
      "entityTypeName":"agilereleasetrain",
      "query":"agileReleaseTrain?select={id,name}&orderby=name"
   },
   "teams":{
      "entityTypeName":"team",
      "filterBy":[
         {
            "selected":"agileReleaseTrains",
            "on":"agileReleaseTrainId",
            "allowUnassigned":true
         }
      ],
      "query":"team?select={id,name,agileReleaseTrainId:agileReleaseTrain.id,icon:emojiicon}&where=isActive==true&orderby=name",
      "iconComponent":"TeamIcon"
   }
}

Keys in entityListMetadata correspond to identifiable element of portfolioAssignments.

entityTypeName specifies all-lowercase entity type.

query specifies APIv2 query that is used to retrieve entity information. At the minimum, selected entities should include id and name properties. If any additional fields are required for filtering, they should also be present in the selector. In this example, selector for agileReleaseTrains is pretty straightforward, while selector for teams also includes additional agileReleaseTrainId property because it's necessary for filtering.

filterBy is an array of filtering rules for the list of entities during assignment. Each filtering rule includes the following properties:

  • selected - specifies one of the keys of entityListMetadata to determine entity ID that will be used for filtering;
  • on - specifies property name in selector that will be matched against selected entity ID
  • allowUnassigned - when set to true, entity list will always contain entities with null values for on property

For example, default filtering rules for teams in the above example means the following:

  • ID of currently selected agileReleaseTrain on the same control should be used for filtering;
  • Only Teams where agileReleaseTrainId matches the ID of currently selected agileReleaseTrain should be visible;
  • Teams that are not assigned to any Agile Release Train (i.e. their agileReleaseTrainId is null) should be visible in the list anyway.

For reference, default entityListMetadata for Teams+Agile Release Trains+Solution Trains looks like this:

{
   "solutionTrains":{
      "entityTypeName":"solutiontrain",
      "query":"solutionTrain?select={id,name}&orderby=name"
   },
   "agileReleaseTrains":{
      "entityTypeName":"agilereleasetrain",
      "filterBy":[
         {
            "selected":"solutionTrains",
            "on":"solutionTrainId"
         }
      ],
      "query":"agileReleaseTrain?select={id,name,solutionTrainId:solutionTrain.id}&orderby=name"
   },
   "teams":{
      "entityTypeName":"team",
      "filterBy":[
         {
            "selected":"agileReleaseTrains",
            "on":"agileReleaseTrainId",
            "allowUnassigned":true
         },
         {
            "selected":"solutionTrains",
            "on":"solutionTrainId",
            "allowUnassigned":true
         }
      ],
      "query":"team?select={id,name,agileReleaseTrainId:agileReleaseTrain.id,solutionTrainId:agileReleaseTrain.solutionTrain.id,icon:emojiicon}&where=isActive==true&orderby=name",
      "iconComponent":"TeamIcon"
   }
}

This configuration corresponds to all the rules previously described for filtering when Solution Trains are enabled.

entityTypesSelectorConfig

This property configures relations between current work item and entity types from entityListMetadata. For example, consider default entityTypesSelectorConfig for Features with Teams+Agile Release Trains:

{
   "agileReleaseTrains":{
      "type":"one",
      "fieldName":"agileReleaseTrain",
      "selector":"{id:agileReleaseTrain.id,name:agileReleaseTrain.name}"
   },
   "teams":{
      "type":"many",
      "fieldName":"assignedTeams",
      "projectionFieldName":"team",
      "linkEntityTypeName":"teamAssignment",
      "selector":"assignedTeams.select({linkId:id,id:team.id,name:team.name,agileReleaseTrainId:team.agileReleaseTrain.id,icon:team.emojiicon})",
      "parentAssignments":{
         "agileReleaseTrains":"agileReleaseTrainId"
      }
   }
}

Each key in entityTypesSelectorConfig should correspond to a key in entityListMetadata. Every key describes the display of a single assignment or assignment list.

There are two primary types of assignment, as seen in this example - one and many, depending on the multiplicity of connections between work item and assignment entity.

When "type": "one" is specified, configuration has the following properties:

  • fieldName - field name of a single reference;
  • selector - APIv2 selector that is used to retrieve assignment status from this work item, for object with id and name properties;
  • readOnly - when present and set to true, "plus" button near entity type will be disabled.

When "type": "many" is specified, configuration has the following properties:

  • fieldName - field name of collection;
  • linkEntityTypeName - entity type name of in-between link entity for many-to-many reference;
  • projectionFieldName - filed name that references opposite entity type on link entity type;
  • selector - APIv2 selector that produces a list of assigned entities to display, at the minimum should include id, name and linkId, and can include additional properties that can be used for parentAssignments;
  • parentAssignments - a mapping where keys correspond to key in entityListMetadata and values specify a property name from the list of assigned entites.

For the above example:

  • Only one Agile Release Train is displayed;
  • It corresponds to agileReleaseTrain field of current entity (Feature in our example);
  • Multiple teams are displayed;
  • Teams list dsiplays items from assignedTeams property of current entity;
  • In-between entity for many-to-many connection between Teams and Features is teamAssignment;
  • Field that references Team entity on teamAssignments is team
  • For each element selector produces id of Team, name of Team, linkId contains ID of in-between entity (teamAssignment) and agileReleaseTrainId is additionally retrieved for parent assignment;
  • Whenever team is selected, its agileReleaseTrainId is used to update the field configured by agileReleaseTrain key, which means that Agile Release Train of selected Team will be automatically assigned to the Feature.

For a more complex example and reference, consider configuration for Teams+Agile Release Trains+Solution Trains for Epics:

{
   "solutionTrains":{
      "type":"one",
      "fieldName":"solutionTrain",
      "selector":"{id:solutionTrain.id,name:solutionTrain.name}"
   },
   "agileReleaseTrains":{
      "type":"many",
      "fieldName":"epicAgileReleaseTrains",
      "projectionFieldName":"agileReleaseTrain",
      "linkEntityTypeName":"epicAgileReleaseTrain",
      "selector":"epicAgileReleaseTrains.select({linkId:id,id:agileReleaseTrain.id,name:agileReleaseTrain.name,solutionTrainId:agileReleaseTrain.solutionTrain.id})",
      "parentAssignments":{
         "solutionTrains":"solutionTrainId"
      }
   },
   "teams":{
      "type":"many",
      "fieldName":"assignedTeams",
      "projectionFieldName":"team",
      "linkEntityTypeName":"teamAssignment",
      "selector":"assignedTeams.select({linkId:id,id:team.id,name:team.name,agileReleaseTrainId:team.agileReleaseTrain.id,solutionTrainId:team.agileReleaseTrain.solutionTrain.id,icon:team.emojiicon})",
      "parentAssignments":{
         "agileReleaseTrains":"agileReleaseTrainId",
         "solutionTrains":"solutionTrainId"
      }
   }
}

Non-standard entity configuration

While default portfolioAssignments is configured to work with Teams, Agile Release Trains and Solution Trains, configuration is flexible enough to support any entity types and any types of relations between work items and assigned entities.

Consider the following example:

{
  "type": "portfolioAssignments",
  "schemaConfig": {
    "entityListMetadata": {
      "solutionTrains": {
        "entityTypeName": "solutiontrain",
        "query": "solutionTrain?select={id,name}"
      },
      "agileReleaseTrains": {
        "entityTypeName": "agilereleasetrain",
        "filterBy": [
          {
            "selected": "solutionTrains",
            "on": "solutionTrainId"
          }
        ],
        "query": "agileReleaseTrain?select={id,name,solutionTrainId:solutionTrain.id}"
      },
      "teams": {
        "entityTypeName": "team",
        "filterBy": [
          {
            "selected": "agileReleaseTrains",
            "on": "agileReleaseTrainId"
          },
          {
            "selected": "solutionTrains",
            "on": "solutionTrainId"
          }
        ],
        "query": "team?select={id,name,agileReleaseTrainId:agileReleaseTrain.id,solutionTrainId:agileReleaseTrain.solutionTrain.id,icon}",
        "iconComponent": "TeamIcon"
      }
    },
    "entityTypesSelectorConfig": {
      "solutionTrains": {
        "type": "many",
        "fieldName": "newPortfolioEpicSolutionTrains",
        "projectionFieldName": "solutionTrain",
        "linkEntityTypeName": "newPortfolioEpicSolutionTrain",
        "selector": "newPortfolioEpicSolutionTrains.select({linkId:id,id:solutionTrain.id,name:solutionTrain.name})"
      },
      "agileReleaseTrains": {
        "type": "many",
        "fieldName": "newPortfolioEpicAgileReleaseTrains",
        "projectionFieldName": "agileReleaseTrain",
        "linkEntityTypeName": "newPortfolioEpicAgileReleaseTrain",
        "selector": "newPortfolioEpicAgileReleaseTrains.select({linkId:id,id:agileReleaseTrain.id,name:agileReleaseTrain.name,solutionTrainId:agileReleaseTrain.solutionTrain.id})",
        "parentAssignments": {
          "solutionTrains": "solutionTrainId"
        }
      },
      "teams": {
        "type": "many",
        "fieldName": "assignedTeams",
        "projectionFieldName": "team",
        "linkEntityTypeName": "teamAssignment",
        "selector": "assignedTeams.select({linkId:id,id:team.id,name:team.name,agileReleaseTrainId:team.agileReleaseTrain.id,solutionTrainId:team.agileReleaseTrain.solutionTrain.id,icon:team.icon})",
        "parentAssignments": {
          "agileReleaseTrains": "agileReleaseTrainId",
          "solutionTrains": "solutionTrainId"
        }
      }
    }
  },
  "componentId": "portfolioAssignments_9d92iok"
}

This configuration replicates the default behavior for Portfolio Epics for non-standard "New Portfolio Epic" entity and corresponding reference property names (newPortfolioEpicAgileReleaseTrains, newPortfolioEpicSolutionTrains).