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
-
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
Screenshots or screen recordings
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.
-
I have evaluated the MR acceptance checklist for this MR.
Edited by Eugenia Grieff