feat: custom fields per project
Text, number, date or option-list fields defined in the project settings (archived, never removed; their type is fixed once saved). Tickets hold them, edited in the side panel, listed under the title and filtered by option in the list view; also over GraphQL, REST (?field=ID:value) and MCP. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -46,6 +46,12 @@ const issueFields = {
|
||||
.optional()
|
||||
.describe('ISO date when work should start (roadmap)'),
|
||||
dueDate: z.string().optional().describe('ISO date, e.g. 2026-11-14'),
|
||||
customFields: z
|
||||
.record(z.string(), z.string().nullable())
|
||||
.optional()
|
||||
.describe(
|
||||
'Custom field id → value (see get_project settings.customFields): SELECT one of its options, DATE YYYY-MM-DD, NUMBER a number. Only the fields to change; null clears one',
|
||||
),
|
||||
};
|
||||
|
||||
type IssueFields = {
|
||||
@@ -57,6 +63,7 @@ type IssueFields = {
|
||||
storyPoints?: number;
|
||||
startDate?: string;
|
||||
dueDate?: string;
|
||||
customFields?: Record<string, string | null>;
|
||||
};
|
||||
|
||||
@Resolver()
|
||||
@@ -142,6 +149,12 @@ export class IssuesResolver {
|
||||
.describe('Only the tickets the user follows'),
|
||||
dueFrom: z.string().optional().describe('Due on or after (ISO date)'),
|
||||
dueTo: z.string().optional().describe('Due on or before (ISO date)'),
|
||||
customFields: z
|
||||
.record(z.string(), z.string())
|
||||
.optional()
|
||||
.describe(
|
||||
'Only tickets holding these custom values (field id → value)',
|
||||
),
|
||||
sort: z
|
||||
.enum(['RECENT', 'RANK'])
|
||||
.default('RECENT')
|
||||
@@ -170,6 +183,7 @@ export class IssuesResolver {
|
||||
watching?: boolean;
|
||||
dueFrom?: string;
|
||||
dueTo?: string;
|
||||
customFields?: Record<string, string>;
|
||||
sort: 'RECENT' | 'RANK';
|
||||
limit: number;
|
||||
offset: number;
|
||||
@@ -198,6 +212,11 @@ export class IssuesResolver {
|
||||
watching: params.watching,
|
||||
dueFrom: params.dueFrom,
|
||||
dueTo: params.dueTo,
|
||||
field: params.customFields
|
||||
? Object.entries(params.customFields).map(
|
||||
([id, value]) => `${id}:${value}`,
|
||||
)
|
||||
: undefined,
|
||||
sort: params.sort,
|
||||
limit: params.limit,
|
||||
offset: params.offset,
|
||||
|
||||
@@ -27,6 +27,7 @@ export const issueLine = (issue: Issue) => ({
|
||||
votes: issue.votes,
|
||||
storyPoints: issue.storyPoints,
|
||||
dueDate: issue.dueDate,
|
||||
customFields: issue.customFields,
|
||||
labels: issue.labels,
|
||||
updatedAt: issue.updatedAt,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user