Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions api/src/models/comment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ export const Comment = z.object({
comment: z.string()
});
export type Comment = z.infer<typeof Comment>;

export interface UpdateComment {
comment: string;
}
38 changes: 38 additions & 0 deletions api/src/models/ticket-comment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { z } from 'zod';

export const TicketComment = z.object({
ticket_comment_id: z.string().uuid(),
ticket_id: z.string().uuid(),
user_identifier: z.string(),
create_date: z.string(),
comment: z.string()
});

export type TicketComment = z.infer<typeof TicketComment>;

export const CreateTicketCommentRequest = z.object({
comment: z.string().min(1).max(3000)
});

export type CreateTicketCommentRequest = z.infer<typeof CreateTicketCommentRequest>;

export const UpdateTicketCommentRequest = z.object({
comment: z.string().min(1).max(3000)
});

export type UpdateTicketCommentRequest = z.infer<typeof UpdateTicketCommentRequest>;

export const CreateTicketComment = z.object({
ticketId: z.string().uuid(),
comment: z.string().min(1).max(3000)
});

export type CreateTicketComment = z.infer<typeof CreateTicketComment>;

export const UpdateTicketComment = z.object({
ticketId: z.string().uuid(),
ticketCommentId: z.string().uuid(),
comment: z.string().min(1).max(3000)
});

export type UpdateTicketComment = z.infer<typeof UpdateTicketComment>;
43 changes: 43 additions & 0 deletions api/src/models/ticket-reference.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { z } from 'zod';

export const TicketRelationshipType = z.enum([
'blocks',
'blocked_by',
'duplicates',
'duplicate_of',
'relates_to',
'resolves',
'resolved_by'
]);

export type TicketRelationshipType = z.infer<typeof TicketRelationshipType>;

export const TicketReference = z.object({
ticket_reference_id: z.string().uuid(),
source_ticket_id: z.string().uuid(),
source_ticket_slug: z.string().regex(/^\d{8}$/),
source_ticket_subject: z.string(),
target_ticket_id: z.string().uuid(),
target_ticket_slug: z.string().regex(/^\d{8}$/),
target_ticket_subject: z.string(),
relationship: TicketRelationshipType,
user_identifier: z.string(),
create_date: z.string()
});

export type TicketReference = z.infer<typeof TicketReference>;

export const CreateTicketReference = z.object({
source_ticket_id: z.string().uuid(),
target_ticket_id: z.string().uuid(),
relationship: TicketRelationshipType
});

export type CreateTicketReference = z.infer<typeof CreateTicketReference>;

export const CreateTicketReferenceRequest = z.object({
target_ticket_id: z.string().uuid(),
relationship: TicketRelationshipType
});

export type CreateTicketReferenceRequest = z.infer<typeof CreateTicketReferenceRequest>;
11 changes: 11 additions & 0 deletions api/src/models/ticket-status.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { z } from 'zod';

export const TicketStatus = z.object({
ticket_status_history_id: z.string().uuid(),
ticket_id: z.string().uuid(),
user_identifier: z.string(),
create_date: z.string(),
status: z.enum(['open', 'closed'])
});

export type TicketStatus = z.infer<typeof TicketStatus>;
71 changes: 71 additions & 0 deletions api/src/models/ticket.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { z } from 'zod';
import { TicketComment } from './ticket-comment';
import { TicketReference } from './ticket-reference';
import { TicketStatus as TicketStatusRecord } from './ticket-status';

export const TicketPriority = z.enum(['low', 'medium', 'high', 'critical']);
export type TicketPriority = z.infer<typeof TicketPriority>;

export const TicketStatus = z.enum(['open', 'closed']);
export type TicketStatus = z.infer<typeof TicketStatus>;

export interface TicketFilters {
team_id?: string;
status?: TicketStatus;
}

export const Ticket = z.object({
ticket_id: z.string().uuid(),
ticket_slug: z.string().regex(/^\d{8}$/),
subject: z.string(),
description: z.string().nullable(),
team_id: z.string().uuid(),
create_date: z.string(),
priority: TicketPriority,
status: TicketStatus
});

export type Ticket = z.infer<typeof Ticket>;

export const TicketSlug = Ticket.pick({ ticket_slug: true });
export type TicketSlug = z.infer<typeof TicketSlug>;

export const CreateTicketRequest = z.object({
subject: z.string().max(100),
description: z.string().max(2000).nullable(),
priority: TicketPriority
});

export type CreateTicketRequest = z.infer<typeof CreateTicketRequest>;

export type CreateTicketPayload = CreateTicketRequest & {
team_id: string;
ticket_slug: string;
};

export const UpdateTicketRequest = z.object({
subject: z.string().max(100).optional(),
description: z.string().max(2000).nullable().optional(),
priority: TicketPriority.optional(),
status: TicketStatus.optional()
});

export type UpdateTicketRequest = z.infer<typeof UpdateTicketRequest>;

export const UpdateTicketStatusRequest = z.object({
status: TicketStatus
});

export type UpdateTicketStatusRequest = z.infer<typeof UpdateTicketStatusRequest>;

export * from './ticket-comment';
export * from './ticket-reference';
export * from './ticket-status';

export const TicketWithHistory = Ticket.extend({
status_history: z.array(TicketStatusRecord),
comments: z.array(TicketComment),
references: z.array(TicketReference)
});

export type TicketWithHistory = z.infer<typeof TicketWithHistory>;
199 changes: 199 additions & 0 deletions api/src/openapi/schemas/ticket.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
import { OpenAPIV3 } from 'openapi-types';
import { paginationResponseSchema } from './pagination';

const TicketPriorityEnum = ['low', 'medium', 'high', 'critical'];
const TicketStatusEnum = ['open', 'closed'];

export const TicketCommentSchema: OpenAPIV3.SchemaObject = {
type: 'object',
required: ['ticket_comment_id', 'ticket_id', 'user_identifier', 'create_date', 'comment'],
properties: {
ticket_comment_id: { type: 'string', format: 'uuid' },
ticket_id: { type: 'string', format: 'uuid' },
user_identifier: { type: 'string' },
create_date: { type: 'string', format: 'date-time' },
comment: { type: 'string' }
}
};

export const TicketReferenceSchema: OpenAPIV3.SchemaObject = {
type: 'object',
required: [
'ticket_reference_id',
'source_ticket_id',
'source_ticket_slug',
'source_ticket_subject',
'target_ticket_id',
'target_ticket_slug',
'target_ticket_subject',
'relationship',
'user_identifier',
'create_date'
],
properties: {
ticket_reference_id: { type: 'string', format: 'uuid' },
source_ticket_id: { type: 'string', format: 'uuid' },
source_ticket_slug: { type: 'string', minLength: 8, maxLength: 8, pattern: String.raw`^\d{8}$` },
source_ticket_subject: { type: 'string', maxLength: 100 },
target_ticket_id: { type: 'string', format: 'uuid' },
target_ticket_slug: { type: 'string', minLength: 8, maxLength: 8, pattern: String.raw`^\d{8}$` },
target_ticket_subject: { type: 'string', maxLength: 100 },
relationship: {
type: 'string',
enum: ['blocks', 'blocked_by', 'duplicates', 'duplicate_of', 'relates_to', 'resolves', 'resolved_by']
},
user_identifier: { type: 'string' },
create_date: { type: 'string', format: 'date-time' }
}
};

export const TicketSchema: OpenAPIV3.SchemaObject = {
type: 'object',
required: ['ticket_id', 'ticket_slug', 'subject', 'team_id', 'create_date', 'priority', 'status'],
properties: {
ticket_id: { type: 'string', format: 'uuid' },
ticket_slug: { type: 'string', minLength: 8, maxLength: 8, pattern: String.raw`^\d{8}$` },
subject: { type: 'string', maxLength: 100 },
description: { type: 'string', maxLength: 2000, nullable: true },
team_id: { type: 'string', format: 'uuid' },
create_date: { type: 'string', format: 'date-time' },
priority: { type: 'string', enum: TicketPriorityEnum },
status: { type: 'string', enum: TicketStatusEnum }
}
};

export const TicketWithHistorySchema: OpenAPIV3.SchemaObject = {
type: 'object',
required: [
'ticket_id',
'ticket_slug',
'subject',
'team_id',
'create_date',
'priority',
'status',
'status_history',
'comments',
'references'
],
properties: {
ticket_id: { type: 'string', format: 'uuid' },
ticket_slug: { type: 'string', minLength: 8, maxLength: 8, pattern: String.raw`^\d{8}$` },
subject: { type: 'string', maxLength: 100 },
description: { type: 'string', maxLength: 2000, nullable: true },
team_id: { type: 'string', format: 'uuid' },
create_date: { type: 'string', format: 'date-time' },
priority: { type: 'string', enum: TicketPriorityEnum },
status: { type: 'string', enum: TicketStatusEnum },
status_history: {
type: 'array',
items: {
type: 'object',
required: ['ticket_status_history_id', 'ticket_id', 'user_identifier', 'create_date', 'status'],
properties: {
ticket_status_history_id: { type: 'string', format: 'uuid' },
ticket_id: { type: 'string', format: 'uuid' },
user_identifier: { type: 'string' },
create_date: { type: 'string', format: 'date-time' },
status: { type: 'string', enum: TicketStatusEnum }
}
}
},
comments: {
type: 'array',
items: TicketCommentSchema
},
references: {
type: 'array',
items: TicketReferenceSchema
}
}
};

export const CreateTicketRequestSchema: OpenAPIV3.SchemaObject = {
type: 'object',
additionalProperties: false,
required: ['subject', 'description', 'priority'],
properties: {
subject: { type: 'string', maxLength: 100 },
description: { type: 'string', maxLength: 2000, nullable: true },
priority: { type: 'string', enum: TicketPriorityEnum }
}
};

export const UpdateTicketRequestSchema: OpenAPIV3.SchemaObject = {
type: 'object',
additionalProperties: false,
properties: {
subject: { type: 'string', maxLength: 100 },
description: { type: 'string', maxLength: 2000, nullable: true },
priority: { type: 'string', enum: TicketPriorityEnum },
status: { type: 'string', enum: TicketStatusEnum }
}
};

export const UpdateTicketStatusRequestSchema: OpenAPIV3.SchemaObject = {
type: 'object',
additionalProperties: false,
required: ['status'],
properties: {
status: { type: 'string', enum: TicketStatusEnum }
}
};

export const CreateTicketCommentRequestSchema: OpenAPIV3.SchemaObject = {
type: 'object',
additionalProperties: false,
required: ['comment'],
properties: {
comment: { type: 'string', minLength: 1, maxLength: 3000 }
}
};

export const UpdateTicketCommentRequestSchema: OpenAPIV3.SchemaObject = {
type: 'object',
additionalProperties: false,
required: ['comment'],
properties: {
comment: { type: 'string', minLength: 1, maxLength: 3000 }
}
};

export const CreateTicketReferenceRequestSchema: OpenAPIV3.SchemaObject = {
type: 'object',
additionalProperties: false,
required: ['target_ticket_id', 'relationship'],
properties: {
target_ticket_id: { type: 'string', format: 'uuid' },
relationship: {
type: 'string',
enum: ['blocks', 'blocked_by', 'duplicates', 'duplicate_of', 'relates_to', 'resolves', 'resolved_by']
}
}
};

export const TicketStatusSchema: OpenAPIV3.SchemaObject = {
type: 'object',
required: ['ticket_id', 'user_identifier', 'create_date'],
properties: {
ticket_status_history_id: { type: 'string', format: 'uuid', nullable: true },
ticket_comment_id: { type: 'string', format: 'uuid', nullable: true },
ticket_id: { type: 'string', format: 'uuid' },
user_identifier: { type: 'string' },
create_date: { type: 'string', format: 'date-time' },
status: { type: 'string', enum: TicketStatusEnum, nullable: true },
comment: { type: 'string', nullable: true }
}
};

export const TicketListResponseSchema: OpenAPIV3.SchemaObject = {
type: 'object',
required: ['tickets', 'pagination'],
properties: {
tickets: {
type: 'array',
items: TicketSchema
},
pagination: paginationResponseSchema
}
};
Loading
Loading