Skip to content

Expose hierarchy widget definition in WorkItemType graphQL type

What does this MR do and why?

Related to #378890 (closed)

In !136616 (merged) we introduced a way to expose widget information for WorkItemType and this MR adds a definition for the hierarchy widget so that given a work item type, we can expose which types are allowed as children.

Database changes

This MR adds two has_many associations to the WorkItems::Type model to be able to retrieve allowed child types:

  • child_restrictions

    SELECT "work_item_hierarchy_restrictions".* FROM "work_item_hierarchy_restrictions" WHERE "work_item_hierarchy_restrictions"."parent_type_id" = 1

    query plan (internal)

  • allowed_child_types

    query for first iteration
       ```sql
          SELECT
              "work_item_types".*
          FROM
              "work_item_types"
              INNER JOIN "work_item_hierarchy_restrictions" ON "work_item_types"."id" = "work_item_hierarchy_restrictions"."child_type_id"
          WHERE
              "work_item_hierarchy_restrictions"."parent_type_id" = 1
          ORDER BY
              "work_item_types"."id" ASC
       ```
    
       [query plan (internal)](https://console.postgres.ai/gitlab/gitlab-production-tunnel-pg12/sessions/24053/commands/76944)
    SELECT
        "work_item_types".*
    FROM
        "work_item_types"
        INNER JOIN "work_item_hierarchy_restrictions" ON "work_item_types"."id" = "work_item_hierarchy_restrictions"."child_type_id"
    WHERE
        "work_item_hierarchy_restrictions"."parent_type_id" = 1
    ORDER BY
        LOWER("work_item_types"."name") ASC

    query plan (internal)

Screenshots or screen recordings

No UI changes

Screenshot_2023-11-21_at_11.12.01

How to set up and validate locally

Use GraphiQL to test the following queries at http://127.0.0.1:3000/-/graphql-explorer

Click to expand queries
  • Work item level
query getAllowedWorkItemChildTypes {
  workItem(id: "gid://gitlab/WorkItem/385") {
    workItemType {
      id
      name
      widgetDefinitions {
        ... on WorkItemWidgetDefinitionHierarchy {
          allowedChildTypes {
            nodes { name }      
          }
        }
      }
    }
  }
}
example response
{
  "data": {
    "workItem": {
      "workItemType": {
        "id": "gid://gitlab/WorkItems::Type/6",
        "name": "Objective",
        "widgetDefinitions": [
          {
            "allowedChildTypes": {
              "nodes": [
                {
                  "name": "Objective"
                },
                {
                  "name": "Key Result"
                }
              ]
            }
          }
        ]
      }
    }
  }
}
  • Project level
query getProjectTypesAllowedChildren{
  project(fullPath: "flightjs/Flight") {
    workItemTypes {
      nodes {
        id
        name
        widgetDefinitions {
          type
          ... on WorkItemWidgetDefinitionHierarchy {
            allowedChildTypes {
              nodes { name }
            }         
          }
        }
      }
    }
  }
}
  • Group level
query getGroupTypesAllowedChildren{
  group(fullPath: "flightjs") {
    workItemTypes {
      nodes {
        id
        name
        widgetDefinitions {
          type
          ... on WorkItemWidgetDefinitionHierarchy {
            allowedChildTypes {
              nodes { name }
            }         
          }
        }
      }
    }
  }
}
example response
{
  "data": {
    "group": {
      "workItemTypes": {
        "nodes": [
          {
            "id": "gid://gitlab/WorkItems::Type/8",
            "name": "Epic",
            "widgetDefinitions": [
              {
                "type": "ASSIGNEES"
              },
              {
                "type": "DESCRIPTION"
              },
              {
                "type": "HIERARCHY",
                "allowedChildTypes": {
                  "nodes": [
                    {
                      "name": "Issue"
                    },
                    {
                      "name": "Epic"
                    }
                  ]
                }
              },
              {
                "type": "LABELS"
              },
              {
                "type": "NOTES"
              },
              {
                "type": "START_AND_DUE_DATE"
              },
              {
                "type": "HEALTH_STATUS"
              },
              {
                "type": "STATUS"
              },
              {
                "type": "NOTIFICATIONS"
              },
              {
                "type": "CURRENT_USER_TODOS"
              },
              {
                "type": "AWARD_EMOJI"
              },
              {
                "type": "LINKED_ITEMS"
              }
            ]
          },
          {
            "id": "gid://gitlab/WorkItems::Type/2",
            "name": "Incident",
            "widgetDefinitions": [
              {
                "type": "ASSIGNEES"
              },
              {
                "type": "DESCRIPTION"
              },
              {
                "type": "HIERARCHY",
                "allowedChildTypes": {
                  "nodes": [
                    {
                      "name": "Task"
                    }
                  ]
                }
              },
              {
                "type": "NOTES"
              },
              {
                "type": "NOTIFICATIONS"
              },
              {
                "type": "CURRENT_USER_TODOS"
              },
              {
                "type": "AWARD_EMOJI"
              },
              {
                "type": "LINKED_ITEMS"
              }
            ]
          },
          {
            "id": "gid://gitlab/WorkItems::Type/1",
            "name": "Issue",
            "widgetDefinitions": [
              {
                "type": "ASSIGNEES"
              },
              {
                "type": "LABELS"
              },
              {
                "type": "DESCRIPTION"
              },
              {
                "type": "HIERARCHY",
                "allowedChildTypes": {
                  "nodes": [
                    {
                      "name": "Task"
                    }
                  ]
                }
              },
              {
                "type": "START_AND_DUE_DATE"
              },
              {
                "type": "MILESTONE"
              },
              {
                "type": "NOTES"
              },
              {
                "type": "ITERATION"
              },
              {
                "type": "WEIGHT"
              },
              {
                "type": "HEALTH_STATUS"
              },
              {
                "type": "NOTIFICATIONS"
              },
              {
                "type": "CURRENT_USER_TODOS"
              },
              {
                "type": "AWARD_EMOJI"
              },
              {
                "type": "LINKED_ITEMS"
              }
            ]
          },
          {
            "id": "gid://gitlab/WorkItems::Type/7",
            "name": "Key Result",
            "widgetDefinitions": [
              {
                "type": "ASSIGNEES"
              },
              {
                "type": "LABELS"
              },
              {
                "type": "DESCRIPTION"
              },
              {
                "type": "HIERARCHY",
                "allowedChildTypes": {
                  "nodes": []
                }
              },
              {
                "type": "START_AND_DUE_DATE"
              },
              {
                "type": "NOTES"
              },
              {
                "type": "HEALTH_STATUS"
              },
              {
                "type": "PROGRESS"
              },
              {
                "type": "NOTIFICATIONS"
              },
              {
                "type": "CURRENT_USER_TODOS"
              },
              {
                "type": "AWARD_EMOJI"
              },
              {
                "type": "LINKED_ITEMS"
              }
            ]
          },
          {
            "id": "gid://gitlab/WorkItems::Type/6",
            "name": "Objective",
            "widgetDefinitions": [
              {
                "type": "ASSIGNEES"
              },
              {
                "type": "LABELS"
              },
              {
                "type": "DESCRIPTION"
              },
              {
                "type": "HIERARCHY",
                "allowedChildTypes": {
                  "nodes": [
                    {
                      "name": "Objective"
                    },
                    {
                      "name": "Key Result"
                    }
                  ]
                }
              },
              {
                "type": "MILESTONE"
              },
              {
                "type": "NOTES"
              },
              {
                "type": "HEALTH_STATUS"
              },
              {
                "type": "PROGRESS"
              },
              {
                "type": "NOTIFICATIONS"
              },
              {
                "type": "CURRENT_USER_TODOS"
              },
              {
                "type": "AWARD_EMOJI"
              },
              {
                "type": "LINKED_ITEMS"
              }
            ]
          },
          {
            "id": "gid://gitlab/WorkItems::Type/4",
            "name": "Requirement",
            "widgetDefinitions": [
              {
                "type": "DESCRIPTION"
              },
              {
                "type": "NOTES"
              },
              {
                "type": "STATUS"
              },
              {
                "type": "REQUIREMENT_LEGACY"
              },
              {
                "type": "TEST_REPORTS"
              },
              {
                "type": "NOTIFICATIONS"
              },
              {
                "type": "CURRENT_USER_TODOS"
              },
              {
                "type": "AWARD_EMOJI"
              },
              {
                "type": "LINKED_ITEMS"
              }
            ]
          },
          {
            "id": "gid://gitlab/WorkItems::Type/5",
            "name": "Task",
            "widgetDefinitions": [
              {
                "type": "ASSIGNEES"
              },
              {
                "type": "LABELS"
              },
              {
                "type": "DESCRIPTION"
              },
              {
                "type": "HIERARCHY",
                "allowedChildTypes": {
                  "nodes": []
                }
              },
              {
                "type": "START_AND_DUE_DATE"
              },
              {
                "type": "MILESTONE"
              },
              {
                "type": "NOTES"
              },
              {
                "type": "ITERATION"
              },
              {
                "type": "WEIGHT"
              },
              {
                "type": "NOTIFICATIONS"
              },
              {
                "type": "CURRENT_USER_TODOS"
              },
              {
                "type": "AWARD_EMOJI"
              },
              {
                "type": "LINKED_ITEMS"
              }
            ]
          },
          {
            "id": "gid://gitlab/WorkItems::Type/3",
            "name": "Test Case",
            "widgetDefinitions": [
              {
                "type": "DESCRIPTION"
              },
              {
                "type": "NOTES"
              },
              {
                "type": "NOTIFICATIONS"
              },
              {
                "type": "CURRENT_USER_TODOS"
              },
              {
                "type": "AWARD_EMOJI"
              },
              {
                "type": "LINKED_ITEMS"
              }
            ]
          },
          {
            "id": "gid://gitlab/WorkItems::Type/9",
            "name": "Ticket",
            "widgetDefinitions": [
              {
                "type": "ASSIGNEES"
              },
              {
                "type": "LABELS"
              },
              {
                "type": "DESCRIPTION"
              },
              {
                "type": "HIERARCHY",
                "allowedChildTypes": {
                  "nodes": [
                    {
                      "name": "Task"
                    }
                  ]
                }
              },
              {
                "type": "START_AND_DUE_DATE"
              },
              {
                "type": "MILESTONE"
              },
              {
                "type": "NOTES"
              },
              {
                "type": "ITERATION"
              },
              {
                "type": "WEIGHT"
              },
              {
                "type": "HEALTH_STATUS"
              },
              {
                "type": "NOTIFICATIONS"
              },
              {
                "type": "CURRENT_USER_TODOS"
              },
              {
                "type": "AWARD_EMOJI"
              },
              {
                "type": "LINKED_ITEMS"
              }
            ]
          }
        ]
      }
    }
  }
}

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Eugenia Grieff

Merge request reports