feat: epics, subtasks and checklists
Tickets can hang from another one of the same project, three levels deep at most (epic → ticket → subtask). The ticket page lists its subtasks with their progress, creates new ones and moves the ticket under an epic; a new Épicas tab shows every epic and how far it has got. Each ticket also gets a checklist for the small steps that don't deserve a ticket. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2178,6 +2178,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "parent",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"description": "Only the tickets hanging from this one (id or key)",
|
||||
"schema": {
|
||||
"example": "WEB-3",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "search",
|
||||
"required": false,
|
||||
@@ -2365,6 +2375,92 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/projects/{project}/epics": {
|
||||
"get": {
|
||||
"description": "With the progress of the tickets hanging from each one (done or cancelled, and story points).",
|
||||
"operationId": "IssuesController_epics",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "project",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"description": "Project id or key",
|
||||
"schema": {
|
||||
"example": "WEB",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/EpicDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid input",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Missing or rejected Pireon token",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Not a member of the project (or not allowed)",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"pireon-oauth": []
|
||||
},
|
||||
{
|
||||
"pireon": []
|
||||
},
|
||||
{}
|
||||
],
|
||||
"summary": "Epics: top-level tickets that group others",
|
||||
"tags": [
|
||||
"Issues"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/issues/{issue}": {
|
||||
"get": {
|
||||
"operationId": "IssuesController_findOne",
|
||||
@@ -2890,6 +2986,457 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/issues/{issue}/parent": {
|
||||
"put": {
|
||||
"description": "Same project, three levels at most (epic → ticket → subtask), no loops. null takes it back to the top.",
|
||||
"operationId": "IssuesController_setParent",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "issue",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"description": "Ticket id or key",
|
||||
"schema": {
|
||||
"example": "WEB-12",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/SetIssueParentDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/CommandResultDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid input",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Missing or rejected Pireon token",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Not a member of the project (or not allowed)",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"409": {
|
||||
"description": "Someone changed it at the same time: retry",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Business rule (e.g. a transition the workflow forbids)",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"pireon-oauth": []
|
||||
},
|
||||
{
|
||||
"pireon": []
|
||||
}
|
||||
],
|
||||
"summary": "Place the ticket under an epic or another ticket",
|
||||
"tags": [
|
||||
"Issues"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/issues/{issue}/checklist": {
|
||||
"post": {
|
||||
"operationId": "IssuesController_addChecklistItem",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "issue",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"description": "Ticket id or key",
|
||||
"schema": {
|
||||
"example": "WEB-12",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ChecklistItemBodyDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/CommandResultDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid input",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Missing or rejected Pireon token",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Not a member of the project (or not allowed)",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"409": {
|
||||
"description": "Someone changed it at the same time: retry",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Business rule (e.g. a transition the workflow forbids)",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"pireon-oauth": []
|
||||
},
|
||||
{
|
||||
"pireon": []
|
||||
}
|
||||
],
|
||||
"summary": "Add a step to the ticket's checklist",
|
||||
"tags": [
|
||||
"Issues"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/issues/{issue}/checklist/{item}": {
|
||||
"patch": {
|
||||
"operationId": "IssuesController_updateChecklistItem",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "issue",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"description": "Ticket id or key",
|
||||
"schema": {
|
||||
"example": "WEB-12",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "item",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/UpdateChecklistItemDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/CommandResultDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid input",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Missing or rejected Pireon token",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Not a member of the project (or not allowed)",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"409": {
|
||||
"description": "Someone changed it at the same time: retry",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Business rule (e.g. a transition the workflow forbids)",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"pireon-oauth": []
|
||||
},
|
||||
{
|
||||
"pireon": []
|
||||
}
|
||||
],
|
||||
"summary": "Reword, tick or untick a checklist step",
|
||||
"tags": [
|
||||
"Issues"
|
||||
]
|
||||
},
|
||||
"delete": {
|
||||
"operationId": "IssuesController_removeChecklistItem",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "issue",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"description": "Ticket id or key",
|
||||
"schema": {
|
||||
"example": "WEB-12",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "item",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/CommandResultDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid input",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Missing or rejected Pireon token",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Not a member of the project (or not allowed)",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"409": {
|
||||
"description": "Someone changed it at the same time: retry",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Business rule (e.g. a transition the workflow forbids)",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiErrorDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"pireon-oauth": []
|
||||
},
|
||||
{
|
||||
"pireon": []
|
||||
}
|
||||
],
|
||||
"summary": "Remove a checklist step",
|
||||
"tags": [
|
||||
"Issues"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/issues/{issue}/links": {
|
||||
"post": {
|
||||
"description": "e.g. WEB-3 DEPENDS_ON API-7, WEB-9 TESTS WEB-3. May cross projects.",
|
||||
@@ -6213,6 +6760,49 @@
|
||||
"commentId"
|
||||
]
|
||||
},
|
||||
"IssueParentDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"key": {
|
||||
"type": "string",
|
||||
"example": "WEB-3"
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"example": "Pago con tarjeta"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"key",
|
||||
"title"
|
||||
]
|
||||
},
|
||||
"ChecklistItemDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"text": {
|
||||
"type": "string",
|
||||
"example": "Actualizar el changelog"
|
||||
},
|
||||
"done": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"text",
|
||||
"done"
|
||||
]
|
||||
},
|
||||
"IssueDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -6340,6 +6930,22 @@
|
||||
"$ref": "#/components/schemas/UserRefDto"
|
||||
}
|
||||
},
|
||||
"parent": {
|
||||
"nullable": true,
|
||||
"description": "The epic or ticket this one breaks down",
|
||||
"type": "object",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/IssueParentDto"
|
||||
}
|
||||
]
|
||||
},
|
||||
"checklist": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ChecklistItemDto"
|
||||
}
|
||||
},
|
||||
"commentCount": {
|
||||
"type": "number"
|
||||
},
|
||||
@@ -6379,6 +6985,8 @@
|
||||
"links",
|
||||
"attachments",
|
||||
"watchers",
|
||||
"parent",
|
||||
"checklist",
|
||||
"commentCount",
|
||||
"createdAt",
|
||||
"updatedAt",
|
||||
@@ -6876,6 +7484,12 @@
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"format": "uuid"
|
||||
},
|
||||
"parent": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"example": "WEB-3",
|
||||
"description": "Epic or ticket of the same project the new one breaks down (id or key)"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -6883,6 +7497,51 @@
|
||||
"title"
|
||||
]
|
||||
},
|
||||
"ChildProgressDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"total": {
|
||||
"type": "number"
|
||||
},
|
||||
"finished": {
|
||||
"type": "number",
|
||||
"description": "Done or cancelled"
|
||||
},
|
||||
"percent": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 100
|
||||
},
|
||||
"storyPoints": {
|
||||
"type": "number"
|
||||
},
|
||||
"finishedStoryPoints": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"total",
|
||||
"finished",
|
||||
"percent",
|
||||
"storyPoints",
|
||||
"finishedStoryPoints"
|
||||
]
|
||||
},
|
||||
"EpicDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"issue": {
|
||||
"$ref": "#/components/schemas/IssueDto"
|
||||
},
|
||||
"progress": {
|
||||
"$ref": "#/components/schemas/ChildProgressDto"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"issue",
|
||||
"progress"
|
||||
]
|
||||
},
|
||||
"UpdateIssueDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -6983,6 +7642,45 @@
|
||||
"releaseId"
|
||||
]
|
||||
},
|
||||
"SetIssueParentDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"parent": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"example": "WEB-3",
|
||||
"description": "Epic or ticket of the same project (id or key), or null to take it back to the top"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"parent"
|
||||
]
|
||||
},
|
||||
"ChecklistItemBodyDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": "string",
|
||||
"example": "Actualizar el changelog",
|
||||
"maxLength": 300
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"text"
|
||||
]
|
||||
},
|
||||
"UpdateChecklistItemDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": "string",
|
||||
"maxLength": 300
|
||||
},
|
||||
"done": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"LinkIssueDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -13,6 +13,11 @@ type Activity {
|
||||
type: String!
|
||||
}
|
||||
|
||||
input AddChecklistItemInput {
|
||||
issueId: ID!
|
||||
text: String!
|
||||
}
|
||||
|
||||
type AreaOption {
|
||||
archived: Boolean!
|
||||
id: String!
|
||||
@@ -57,6 +62,23 @@ input ChangeIssueStatusInput {
|
||||
status: String!
|
||||
}
|
||||
|
||||
"""A step inside a ticket that does not deserve a ticket of its own"""
|
||||
type ChecklistItem {
|
||||
done: Boolean!
|
||||
id: ID!
|
||||
text: String!
|
||||
}
|
||||
|
||||
"""How far the tickets hanging from one have got"""
|
||||
type ChildProgress {
|
||||
"""Done or cancelled"""
|
||||
finished: Int!
|
||||
finishedStoryPoints: Int!
|
||||
percent: Int!
|
||||
storyPoints: Int!
|
||||
total: Int!
|
||||
}
|
||||
|
||||
"""
|
||||
Writes are acknowledged immediately; the read model catches up asynchronously. Wait for a subscription event with version >= this version to see the change.
|
||||
"""
|
||||
@@ -121,6 +143,9 @@ input CreateIssueInput {
|
||||
"""Figma frame for UI changes"""
|
||||
figmaUrl: String
|
||||
labels: [String!]
|
||||
|
||||
"""Epic or ticket of the same project the new one breaks down"""
|
||||
parentId: ID
|
||||
priority: IssuePriority
|
||||
projectId: ID!
|
||||
releaseId: ID
|
||||
@@ -172,6 +197,12 @@ type DurationStats {
|
||||
p85Days: Float
|
||||
}
|
||||
|
||||
"""A top-level ticket that groups others, with their progress"""
|
||||
type Epic {
|
||||
issue: Issue!
|
||||
progress: ChildProgress!
|
||||
}
|
||||
|
||||
type FlowSeries {
|
||||
counts: [Int!]!
|
||||
status: String!
|
||||
@@ -185,6 +216,7 @@ type Issue {
|
||||
area: String
|
||||
assignee: UserRef
|
||||
attachments: [Attachment!]!
|
||||
checklist: [ChecklistItem!]!
|
||||
commentCount: Int!
|
||||
comments(limit: Int! = 50, offset: Int! = 0): CommentPage!
|
||||
createdAt: String!
|
||||
@@ -204,6 +236,9 @@ type Issue {
|
||||
linkedIssues: [Issue!]!
|
||||
links: [IssueLink!]!
|
||||
number: Int!
|
||||
|
||||
"""The epic or ticket this one breaks down"""
|
||||
parent: IssueParent
|
||||
priority: IssuePriority!
|
||||
projectId: ID!
|
||||
projectKey: String!
|
||||
@@ -237,6 +272,9 @@ input IssueFilterInput {
|
||||
assigneeId: ID
|
||||
categories: [StatusCategory!]
|
||||
labels: [String!]
|
||||
|
||||
"""Only the tickets hanging from this one"""
|
||||
parentId: ID
|
||||
priorities: [IssuePriority!]
|
||||
projectId: ID!
|
||||
releaseId: ID
|
||||
@@ -269,6 +307,13 @@ type IssuePage {
|
||||
total: Int!
|
||||
}
|
||||
|
||||
"""The ticket another one hangs from"""
|
||||
type IssueParent {
|
||||
id: ID!
|
||||
key: String!
|
||||
title: String!
|
||||
}
|
||||
|
||||
enum IssuePriority {
|
||||
CRITICAL
|
||||
HIGH
|
||||
@@ -317,6 +362,8 @@ type Me {
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
"""Add a step to a ticket's checklist"""
|
||||
addChecklistItem(input: AddChecklistItemInput!): CommandResult!
|
||||
addComment(body: String!, issueId: ID!): CommandResult!
|
||||
|
||||
"""Add a Pireon user to the project"""
|
||||
@@ -357,14 +404,23 @@ type Mutation {
|
||||
Remove a file from a ticket (whoever uploaded it, or an owner/admin). Upload with the REST API.
|
||||
"""
|
||||
removeAttachment(attachmentId: ID!, issueId: ID!): CommandResult!
|
||||
removeChecklistItem(issueId: ID!, itemId: ID!): CommandResult!
|
||||
removeProjectMember(projectId: ID!, userId: ID!): CommandResult!
|
||||
|
||||
"""
|
||||
Place a ticket under an epic or another ticket of the same project (null: back to the top). Three levels at most: epic → ticket → subtask.
|
||||
"""
|
||||
setIssueParent(issueId: ID!, parentId: ID): CommandResult!
|
||||
|
||||
"""Put a ticket in a release (null removes it)"""
|
||||
setIssueRelease(issueId: ID!, releaseId: ID): CommandResult!
|
||||
unlinkIssues(input: LinkIssuesInput!): CommandResult!
|
||||
|
||||
"""Stop following a ticket"""
|
||||
unwatchIssue(issueId: ID!): CommandResult!
|
||||
|
||||
"""Reword, tick or untick a checklist step"""
|
||||
updateChecklistItem(input: UpdateChecklistItemInput!): CommandResult!
|
||||
updateIssue(input: UpdateIssueInput!): CommandResult!
|
||||
updateNotificationSettings(email: Boolean!): NotificationSettings!
|
||||
updateProject(input: UpdateProjectInput!): CommandResult!
|
||||
@@ -541,6 +597,11 @@ type Query {
|
||||
limit: Int! = 50
|
||||
projectId: ID!
|
||||
): [Activity!]!
|
||||
|
||||
"""
|
||||
A project's epics: top-level tickets that group others, with the progress of those
|
||||
"""
|
||||
epics(projectId: ID!): [Epic!]!
|
||||
issue(
|
||||
"""Issue id or key (e.g. "TS-42")"""
|
||||
idOrKey: String!
|
||||
@@ -677,6 +738,13 @@ type Throughput {
|
||||
week: String!
|
||||
}
|
||||
|
||||
input UpdateChecklistItemInput {
|
||||
done: Boolean
|
||||
issueId: ID!
|
||||
itemId: ID!
|
||||
text: String
|
||||
}
|
||||
|
||||
input UpdateIssueInput {
|
||||
"""An area id"""
|
||||
area: String
|
||||
|
||||
@@ -363,6 +363,26 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/projects/{project}/epics": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
/**
|
||||
* Epics: top-level tickets that group others
|
||||
* @description With the progress of the tickets hanging from each one (done or cancelled, and story points).
|
||||
*/
|
||||
get: operations["IssuesController_epics"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/issues/{issue}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -435,6 +455,61 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/issues/{issue}/parent": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
/**
|
||||
* Place the ticket under an epic or another ticket
|
||||
* @description Same project, three levels at most (epic → ticket → subtask), no loops. null takes it back to the top.
|
||||
*/
|
||||
put: operations["IssuesController_setParent"];
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/issues/{issue}/checklist": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
/** Add a step to the ticket's checklist */
|
||||
post: operations["IssuesController_addChecklistItem"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/issues/{issue}/checklist/{item}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post?: never;
|
||||
/** Remove a checklist step */
|
||||
delete: operations["IssuesController_removeChecklistItem"];
|
||||
options?: never;
|
||||
head?: never;
|
||||
/** Reword, tick or untick a checklist step */
|
||||
patch: operations["IssuesController_updateChecklistItem"];
|
||||
trace?: never;
|
||||
};
|
||||
"/api/issues/{issue}/links": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -1071,6 +1146,21 @@ export interface components {
|
||||
*/
|
||||
commentId: string | null;
|
||||
};
|
||||
IssueParentDto: {
|
||||
/** Format: uuid */
|
||||
id: string;
|
||||
/** @example WEB-3 */
|
||||
key: string;
|
||||
/** @example Pago con tarjeta */
|
||||
title: string;
|
||||
};
|
||||
ChecklistItemDto: {
|
||||
/** Format: uuid */
|
||||
id: string;
|
||||
/** @example Actualizar el changelog */
|
||||
text: string;
|
||||
done: boolean;
|
||||
};
|
||||
IssueDto: {
|
||||
/** Format: uuid */
|
||||
id: string;
|
||||
@@ -1116,6 +1206,9 @@ export interface components {
|
||||
attachments: components["schemas"]["AttachmentDto"][];
|
||||
/** @description People following it */
|
||||
watchers: components["schemas"]["UserRefDto"][];
|
||||
/** @description The epic or ticket this one breaks down */
|
||||
parent: components["schemas"]["IssueParentDto"] | null;
|
||||
checklist: components["schemas"]["ChecklistItemDto"][];
|
||||
commentCount: number;
|
||||
/** Format: date-time */
|
||||
createdAt: string;
|
||||
@@ -1266,6 +1359,23 @@ export interface components {
|
||||
assigneeId?: string | null;
|
||||
/** Format: uuid */
|
||||
releaseId?: string | null;
|
||||
/**
|
||||
* @description Epic or ticket of the same project the new one breaks down (id or key)
|
||||
* @example WEB-3
|
||||
*/
|
||||
parent?: string | null;
|
||||
};
|
||||
ChildProgressDto: {
|
||||
total: number;
|
||||
/** @description Done or cancelled */
|
||||
finished: number;
|
||||
percent: number;
|
||||
storyPoints: number;
|
||||
finishedStoryPoints: number;
|
||||
};
|
||||
EpicDto: {
|
||||
issue: components["schemas"]["IssueDto"];
|
||||
progress: components["schemas"]["ChildProgressDto"];
|
||||
};
|
||||
UpdateIssueDto: {
|
||||
description?: string | null;
|
||||
@@ -1308,6 +1418,21 @@ export interface components {
|
||||
*/
|
||||
releaseId: string | null;
|
||||
};
|
||||
SetIssueParentDto: {
|
||||
/**
|
||||
* @description Epic or ticket of the same project (id or key), or null to take it back to the top
|
||||
* @example WEB-3
|
||||
*/
|
||||
parent: string | null;
|
||||
};
|
||||
ChecklistItemBodyDto: {
|
||||
/** @example Actualizar el changelog */
|
||||
text: string;
|
||||
};
|
||||
UpdateChecklistItemDto: {
|
||||
text?: string;
|
||||
done?: boolean;
|
||||
};
|
||||
LinkIssueDto: {
|
||||
type: components["schemas"]["IssueLinkType"];
|
||||
/**
|
||||
@@ -2890,6 +3015,8 @@ export interface operations {
|
||||
unassigned?: boolean;
|
||||
releaseId?: string;
|
||||
label?: string[];
|
||||
/** @description Only the tickets hanging from this one (id or key) */
|
||||
parent?: string;
|
||||
/** @description Matches key, title or description */
|
||||
search?: string;
|
||||
};
|
||||
@@ -3028,6 +3155,64 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
};
|
||||
IssuesController_epics: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
/** @description Project id or key */
|
||||
project: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["EpicDto"][];
|
||||
};
|
||||
};
|
||||
/** @description Invalid input */
|
||||
400: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Missing or rejected Pireon token */
|
||||
401: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Not a member of the project (or not allowed) */
|
||||
403: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Not found */
|
||||
404: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
IssuesController_findOne: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -3406,6 +3591,324 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
};
|
||||
IssuesController_setParent: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
/** @description Ticket id or key */
|
||||
issue: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["SetIssueParentDto"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["CommandResultDto"];
|
||||
};
|
||||
};
|
||||
/** @description Invalid input */
|
||||
400: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Missing or rejected Pireon token */
|
||||
401: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Not a member of the project (or not allowed) */
|
||||
403: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Not found */
|
||||
404: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Someone changed it at the same time: retry */
|
||||
409: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Business rule (e.g. a transition the workflow forbids) */
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
IssuesController_addChecklistItem: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
/** @description Ticket id or key */
|
||||
issue: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ChecklistItemBodyDto"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
201: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["CommandResultDto"];
|
||||
};
|
||||
};
|
||||
/** @description Invalid input */
|
||||
400: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Missing or rejected Pireon token */
|
||||
401: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Not a member of the project (or not allowed) */
|
||||
403: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Not found */
|
||||
404: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Someone changed it at the same time: retry */
|
||||
409: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Business rule (e.g. a transition the workflow forbids) */
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
IssuesController_removeChecklistItem: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
/** @description Ticket id or key */
|
||||
issue: string;
|
||||
item: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["CommandResultDto"];
|
||||
};
|
||||
};
|
||||
/** @description Invalid input */
|
||||
400: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Missing or rejected Pireon token */
|
||||
401: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Not a member of the project (or not allowed) */
|
||||
403: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Not found */
|
||||
404: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Someone changed it at the same time: retry */
|
||||
409: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Business rule (e.g. a transition the workflow forbids) */
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
IssuesController_updateChecklistItem: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
/** @description Ticket id or key */
|
||||
issue: string;
|
||||
item: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["UpdateChecklistItemDto"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["CommandResultDto"];
|
||||
};
|
||||
};
|
||||
/** @description Invalid input */
|
||||
400: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Missing or rejected Pireon token */
|
||||
401: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Not a member of the project (or not allowed) */
|
||||
403: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Not found */
|
||||
404: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Someone changed it at the same time: retry */
|
||||
409: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
/** @description Business rule (e.g. a transition the workflow forbids) */
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiErrorDto"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
IssuesController_link: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
|
||||
@@ -28,6 +28,7 @@ describe('appRoutes', () => {
|
||||
'',
|
||||
'board',
|
||||
'issues/:issueKey',
|
||||
'epics',
|
||||
'releases',
|
||||
'dashboard',
|
||||
'analytics',
|
||||
|
||||
Reference in New Issue
Block a user