feat: templates per ticket type

Each ticket type can carry a starting description and a checklist, edited
in the project settings. New tickets of that type get the description
when they come without one and always get the checklist; the new ticket
form says what the template will add.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 15:58:37 +02:00
parent 8994590b54
commit 5863d773be
23 changed files with 565 additions and 9 deletions

View File

@@ -9051,6 +9051,25 @@
"support"
]
},
"IssueTemplateDto": {
"type": "object",
"properties": {
"description": {
"type": "string",
"nullable": true
},
"checklist": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"description",
"checklist"
]
},
"IssueTypeOptionDto": {
"type": "object",
"properties": {
@@ -9078,6 +9097,14 @@
},
"archived": {
"type": "boolean"
},
"template": {
"description": "What a new ticket of the type starts with",
"allOf": [
{
"$ref": "#/components/schemas/IssueTemplateDto"
}
]
}
},
"required": [
@@ -9352,6 +9379,23 @@
"to"
]
},
"IssueTemplateBodyDto": {
"type": "object",
"properties": {
"description": {
"type": "string",
"nullable": true,
"maxLength": 5000
},
"checklist": {
"maxItems": 20,
"type": "array",
"items": {
"type": "string"
}
}
}
},
"IssueTypeOptionBodyDto": {
"type": "object",
"properties": {
@@ -9381,6 +9425,16 @@
"archived": {
"type": "boolean",
"default": false
},
"template": {
"nullable": true,
"description": "What a new ticket of the type starts with",
"type": "object",
"allOf": [
{
"$ref": "#/components/schemas/IssueTemplateBodyDto"
}
]
}
},
"required": [

View File

@@ -491,12 +491,27 @@ enum IssueSort {
RECENT
}
"""What a new ticket of the type starts with"""
type IssueTemplate {
"""Steps added to every new ticket"""
checklist: [String!]!
"""Used when the ticket comes without a description"""
description: String
}
input IssueTemplateInput {
checklist: [String!]! = []
description: String
}
type IssueTypeOption {
archived: Boolean!
color: String!
icon: String!
id: String!
name: String!
template: IssueTemplate
}
input IssueTypeOptionInput {
@@ -505,6 +520,7 @@ input IssueTypeOptionInput {
icon: String!
id: String!
name: String!
template: IssueTemplateInput
}
enum LinkDirection {

View File

@@ -1368,6 +1368,10 @@ export interface components {
};
/** @enum {string} */
TypeIcon: "bug" | "feature" | "palette" | "task" | "qa" | "flag" | "star-fill" | "rocket" | "document" | "light-bulb" | "key" | "support";
IssueTemplateDto: {
description: string | null;
checklist: string[];
};
IssueTypeOptionDto: {
/** @example BUG */
id: string;
@@ -1376,6 +1380,8 @@ export interface components {
icon: components["schemas"]["TypeIcon"];
color: components["schemas"]["SettingColor"];
archived: boolean;
/** @description What a new ticket of the type starts with */
template?: components["schemas"]["IssueTemplateDto"];
};
AreaOptionDto: {
/** @example FRONTEND */
@@ -1478,6 +1484,10 @@ export interface components {
*/
to: string[];
};
IssueTemplateBodyDto: {
description?: string | null;
checklist?: string[];
};
IssueTypeOptionBodyDto: {
/** @example SPIKE */
id: string;
@@ -1487,6 +1497,8 @@ export interface components {
color: components["schemas"]["SettingColor"];
/** @default false */
archived: boolean;
/** @description What a new ticket of the type starts with */
template?: components["schemas"]["IssueTemplateBodyDto"] | null;
};
AreaOptionBodyDto: {
/** @example DATA */