From b014ded5fdedb6ba5d75bab4d45f0da7097e524f Mon Sep 17 00:00:00 2001 From: Dhairyashil Shinde <93669429+dhairyashiil@users.noreply.github.com> Date: Fri, 5 Dec 2025 19:51:48 +0530 Subject: [PATCH] feat: api v2 event types ordering - user, team, org (#25177) * feat: api-v2-event-types-ordering * sort team and org event types * revert: remove accidental changes to api-auth.strategy.ts * docs: add ordering documentation and test for event types endpoints - Added test assertion to verify event types are returned in descending order by ID (newest first) - Added API documentation to user event types endpoint describing default ordering behavior - Added API documentation to team event types endpoint describing default ordering behavior - Added API documentation to organization event types endpoints describing default ordering behavior Addresses PR feedback to document and test the ordering behavior introduced in the API v2 event types ordering feature. * feat: add optional sortCreatedAt parameter to event types endpoints - Add sortCreatedAt query parameter (SortOrderType: "asc" | "desc") to all event types endpoints - Define SortOrder enum and SortOrderType in pagination.input.ts for reusability - When not provided, no explicit ordering is applied (backward compatible) - Update user, team, and organization event types endpoints - Add comprehensive e2e tests for all sorting scenarios - Fix circular dependency in platform-types import - Thread sortCreatedAt through all service layers - Use spread pattern for conditional orderBy to avoid empty array issues Addresses PR feedback to make ordering opt-in rather than changing default behavior --- .../event-types.controller.e2e-spec.ts | 50 ++++++++++++++++- .../controllers/event-types.controller.ts | 2 + .../event-types.repository.ts | 7 ++- .../services/event-types.service.ts | 20 ++++--- .../organizations-event-types.controller.ts | 25 ++++++--- .../organizations-event-types.repository.ts | 10 +++- .../organizations-event-types.service.ts | 16 ++++-- .../teams-event-types.controller.ts | 10 +++- .../services/teams-event-types.service.ts | 6 +- .../teams-event-types.repository.ts | 5 +- docs/api-reference/v2/openapi.json | 55 ++++++++++++++++++- .../inputs/get-event-types-query.input.ts | 30 +++++++++- .../types/pagination/pagination.input.ts | 7 +++ 13 files changed, 209 insertions(+), 34 deletions(-) diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/controllers/event-types.controller.e2e-spec.ts b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/controllers/event-types.controller.e2e-spec.ts index 4ba4771e7f..8138d7e133 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/controllers/event-types.controller.e2e-spec.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/controllers/event-types.controller.e2e-spec.ts @@ -640,9 +640,9 @@ describe("Event types Endpoints", () => { hiddenEventType = responseBody.data; }); - it(`/GET/event-types by username`, async () => { + it(`/GET/event-types by username with sortCreatedAt=desc`, async () => { const response = await request(app.getHttpServer()) - .get(`/api/v2/event-types?username=${user.username}`) + .get(`/api/v2/event-types?username=${user.username}&sortCreatedAt=desc`) .set(CAL_API_VERSION_HEADER, VERSION_2024_06_14) .set("Authorization", `Bearer ${apiKeyString}`) .expect(200); @@ -653,6 +653,12 @@ describe("Event types Endpoints", () => { expect(responseBody.data).toBeDefined(); expect(responseBody.data?.length).toEqual(2); + // Verify ordering: event types are returned newest to oldest when sortCreatedAt=desc + // hiddenEventType was created after eventType, so it should have a higher ID and appear first + expect(responseBody.data[0].id).toBeGreaterThan(responseBody.data[1].id); + expect(responseBody.data[0].id).toEqual(hiddenEventType.id); + expect(responseBody.data[1].id).toEqual(eventType.id); + const fetchedEventType = responseBody.data?.find((et) => et.id === eventType.id); const fetchedHiddenEventType = responseBody.data?.find((et) => et.id === hiddenEventType.id); @@ -711,6 +717,46 @@ describe("Event types Endpoints", () => { expect(fetchedEventType?.hidden).toEqual(false); }); + it(`/GET/event-types by username with sortCreatedAt=asc`, async () => { + const response = await request(app.getHttpServer()) + .get(`/api/v2/event-types?username=${user.username}&sortCreatedAt=asc`) + .set(CAL_API_VERSION_HEADER, VERSION_2024_06_14) + .set("Authorization", `Bearer ${apiKeyString}`) + .expect(200); + + const responseBody: ApiSuccessResponse = response.body; + + expect(responseBody.status).toEqual(SUCCESS_STATUS); + expect(responseBody.data).toBeDefined(); + expect(responseBody.data?.length).toEqual(2); + + // Verify ordering: event types are returned oldest to newest when sortCreatedAt=asc + // eventType was created before hiddenEventType, so it should have a lower ID and appear first + expect(responseBody.data[0].id).toBeLessThan(responseBody.data[1].id); + expect(responseBody.data[0].id).toEqual(eventType.id); + expect(responseBody.data[1].id).toEqual(hiddenEventType.id); + }); + + it(`/GET/event-types by username without sortCreatedAt parameter`, async () => { + const response = await request(app.getHttpServer()) + .get(`/api/v2/event-types?username=${user.username}`) + .set(CAL_API_VERSION_HEADER, VERSION_2024_06_14) + .set("Authorization", `Bearer ${apiKeyString}`) + .expect(200); + + const responseBody: ApiSuccessResponse = response.body; + + expect(responseBody.status).toEqual(SUCCESS_STATUS); + expect(responseBody.data).toBeDefined(); + expect(responseBody.data?.length).toEqual(2); + + // Without sortCreatedAt, no specific order is guaranteed + // Just verify both event types are present + const ids = responseBody.data.map((et) => et.id); + expect(ids).toContain(eventType.id); + expect(ids).toContain(hiddenEventType.id); + }); + it(`/GET/event-types by username should not return hidden event type if no auth provided`, async () => { const response = await request(app.getHttpServer()) .get(`/api/v2/event-types?username=${user.username}`) diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/controllers/event-types.controller.ts b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/controllers/event-types.controller.ts index 86dec46ed8..2a1f83cddc 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/controllers/event-types.controller.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/controllers/event-types.controller.ts @@ -155,6 +155,8 @@ export class EventTypesController_2024_06_14 { summary: "Get all event types", description: `Hidden event types are returned only if authentication is provided and it belongs to the event type owner. + Use the optional \`sortCreatedAt\` query parameter to order results by creation date (by ID). Accepts "asc" (oldest first) or "desc" (newest first). When not provided, no explicit ordering is applied. + Please make sure to pass in the cal-api-version header value as mentioned in the Headers section. Not passing the correct value will default to an older version of this endpoint. `, }) diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts index 4f1588db8c..63af9164fd 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts @@ -3,6 +3,7 @@ import { PrismaReadService } from "@/modules/prisma/prisma-read.service"; import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; import { Injectable } from "@nestjs/common"; +import type { SortOrderType } from "@calcom/platform-types"; import type { Prisma } from "@calcom/prisma/client"; @Injectable() @@ -67,21 +68,23 @@ export class EventTypesRepository_2024_06_14 { }); } - async getUserEventTypes(userId: number) { + async getUserEventTypes(userId: number, sortCreatedAt?: SortOrderType) { return this.dbRead.prisma.eventType.findMany({ where: { userId, }, + ...(sortCreatedAt && { orderBy: { id: sortCreatedAt } }), include: { users: true, schedule: true, destinationCalendar: true }, }); } - async getUserEventTypesPublic(userId: number) { + async getUserEventTypesPublic(userId: number, sortCreatedAt?: SortOrderType) { return this.dbRead.prisma.eventType.findMany({ where: { userId, hidden: false, }, + ...(sortCreatedAt && { orderBy: { id: sortCreatedAt } }), include: { users: true, schedule: true, destinationCalendar: true }, }); } diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/event-types.service.ts b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/event-types.service.ts index a24ccb365a..550e12f89c 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/event-types.service.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/event-types.service.ts @@ -22,7 +22,7 @@ import { getEventTypesPublic, EventTypesPublic, } from "@calcom/platform-libraries/event-types"; -import type { GetEventTypesQuery_2024_06_14 } from "@calcom/platform-types"; +import type { GetEventTypesQuery_2024_06_14, SortOrderType } from "@calcom/platform-types"; import type { EventType } from "@calcom/prisma/client"; @Injectable() @@ -160,15 +160,16 @@ export class EventTypesService_2024_06_14 { orgSlug?: string; orgId?: number; authUser?: AuthOptionalUser; + sortCreatedAt?: SortOrderType; }) { const user = await this.usersRepository.findByUsername(params.username, params.orgSlug, params.orgId); if (!user) { return []; } if (params.authUser?.id !== user.id) { - return await this.getUserEventTypesPublic(user.id); + return await this.getUserEventTypesPublic(user.id, params.sortCreatedAt); } - return await this.getUserEventTypes(user.id); + return await this.getUserEventTypes(user.id, params.sortCreatedAt); } async getUserToCreateEvent(user: UserWithProfile) { @@ -211,16 +212,16 @@ export class EventTypesService_2024_06_14 { }; } - async getUserEventTypes(userId: number) { - const eventTypes = await this.eventTypesRepository.getUserEventTypes(userId); + async getUserEventTypes(userId: number, sortCreatedAt?: SortOrderType) { + const eventTypes = await this.eventTypesRepository.getUserEventTypes(userId, sortCreatedAt); return eventTypes.map((eventType) => { return { ownerId: userId, ...eventType }; }); } - async getUserEventTypesPublic(userId: number) { - const eventTypes = await this.eventTypesRepository.getUserEventTypesPublic(userId); + async getUserEventTypesPublic(userId: number, sortCreatedAt?: SortOrderType) { + const eventTypes = await this.eventTypesRepository.getUserEventTypesPublic(userId, sortCreatedAt); return eventTypes.map((eventType) => { return { ownerId: userId, ...eventType }; @@ -237,7 +238,7 @@ export class EventTypesService_2024_06_14 { } async getEventTypes(queryParams: GetEventTypesQuery_2024_06_14, authUser?: AuthOptionalUser) { - const { username, eventSlug, usernames, orgSlug, orgId } = queryParams; + const { username, eventSlug, usernames, orgSlug, orgId, sortCreatedAt } = queryParams; if (username && eventSlug) { const eventType = await this.getEventTypeByUsernameAndSlug({ username, @@ -255,6 +256,7 @@ export class EventTypesService_2024_06_14 { orgSlug, orgId, authUser, + sortCreatedAt, }); } @@ -264,7 +266,7 @@ export class EventTypesService_2024_06_14 { } if (authUser?.id) { - return await this.getUserEventTypes(authUser.id); + return await this.getUserEventTypes(authUser.id, sortCreatedAt); } return []; diff --git a/apps/api/v2/src/modules/organizations/event-types/organizations-event-types.controller.ts b/apps/api/v2/src/modules/organizations/event-types/organizations-event-types.controller.ts index dd3016e034..d801cbeda9 100644 --- a/apps/api/v2/src/modules/organizations/event-types/organizations-event-types.controller.ts +++ b/apps/api/v2/src/modules/organizations/event-types/organizations-event-types.controller.ts @@ -47,8 +47,8 @@ import { ERROR_STATUS, SUCCESS_STATUS } from "@calcom/platform-constants"; import { handleCreatePhoneCall } from "@calcom/platform-libraries"; import { CreateTeamEventTypeInput_2024_06_14, + GetOrganizationEventTypesQuery_2024_06_14, GetTeamEventTypesQuery_2024_06_14, - SkipTakePagination, TeamEventTypeOutput_2024_06_14, UpdateTeamEventTypeInput_2024_06_14, } from "@calcom/platform-types"; @@ -159,12 +159,16 @@ export class OrganizationsEventTypesController { @UseGuards(IsOrgGuard, IsTeamInOrg, IsAdminAPIEnabledGuard) @Get("/teams/:teamId/event-types") - @ApiOperation({ summary: "Get team event types" }) + @ApiOperation({ + summary: "Get team event types", + description: + 'Use the optional `sortCreatedAt` query parameter to order results by creation date (by ID). Accepts "asc" (oldest first) or "desc" (newest first). When not provided, no explicit ordering is applied.', + }) async getTeamEventTypes( @Param("teamId", ParseIntPipe) teamId: number, @Query() queryParams: GetTeamEventTypesQuery_2024_06_14 ): Promise { - const { eventSlug, hostsLimit } = queryParams; + const { eventSlug, hostsLimit, sortCreatedAt } = queryParams; if (eventSlug) { const eventType = await this.organizationsEventTypesService.getTeamEventTypeBySlug( @@ -179,7 +183,7 @@ export class OrganizationsEventTypesController { }; } - const eventTypes = await this.organizationsEventTypesService.getTeamEventTypes(teamId); + const eventTypes = await this.organizationsEventTypesService.getTeamEventTypes(teamId, sortCreatedAt); return { status: SUCCESS_STATUS, @@ -191,16 +195,21 @@ export class OrganizationsEventTypesController { @PlatformPlan("ESSENTIALS") @UseGuards(ApiAuthGuard, IsOrgGuard, RolesGuard, PlatformPlanGuard, IsAdminAPIEnabledGuard) @Get("/teams/event-types") - @ApiOperation({ summary: "Get all team event types" }) + @ApiOperation({ + summary: "Get all team event types", + description: + 'Use the optional `sortCreatedAt` query parameter to order results by creation date (by ID). Accepts "asc" (oldest first) or "desc" (newest first). When not provided, no explicit ordering is applied.', + }) async getTeamsEventTypes( @Param("orgId", ParseIntPipe) orgId: number, - @Query() queryParams: SkipTakePagination + @Query() queryParams: GetOrganizationEventTypesQuery_2024_06_14 ): Promise { - const { skip, take } = queryParams; + const { skip, take, sortCreatedAt } = queryParams; const eventTypes = await this.organizationsEventTypesService.getOrganizationsTeamsEventTypes( orgId, skip, - take + take, + sortCreatedAt ); return { diff --git a/apps/api/v2/src/modules/organizations/event-types/organizations-event-types.repository.ts b/apps/api/v2/src/modules/organizations/event-types/organizations-event-types.repository.ts index 5d337bc577..93f6cfd610 100644 --- a/apps/api/v2/src/modules/organizations/event-types/organizations-event-types.repository.ts +++ b/apps/api/v2/src/modules/organizations/event-types/organizations-event-types.repository.ts @@ -1,16 +1,24 @@ import { PrismaReadService } from "@/modules/prisma/prisma-read.service"; import { Injectable } from "@nestjs/common"; +import type { SortOrderType } from "@calcom/platform-types"; + @Injectable() export class OrganizationsEventTypesRepository { constructor(private readonly dbRead: PrismaReadService) {} - async getOrganizationTeamsEventTypes(orgId: number, skip: number, take: number) { + async getOrganizationTeamsEventTypes( + orgId: number, + skip: number, + take: number, + sortCreatedAt?: SortOrderType + ) { return this.dbRead.prisma.eventType.findMany({ where: { team: { parentId: orgId, }, }, + ...(sortCreatedAt && { orderBy: { id: sortCreatedAt } }), skip, take, include: { users: true, schedule: true, hosts: true, destinationCalendar: true }, diff --git a/apps/api/v2/src/modules/organizations/event-types/services/organizations-event-types.service.ts b/apps/api/v2/src/modules/organizations/event-types/services/organizations-event-types.service.ts index d38fa37f90..10267b55e3 100644 --- a/apps/api/v2/src/modules/organizations/event-types/services/organizations-event-types.service.ts +++ b/apps/api/v2/src/modules/organizations/event-types/services/organizations-event-types.service.ts @@ -1,4 +1,6 @@ import { MembershipsRepository } from "@/modules/memberships/memberships.repository"; + +import type { SortOrderType } from "@calcom/platform-types"; import { OrganizationsEventTypesRepository } from "@/modules/organizations/event-types/organizations-event-types.repository"; import { TransformedCreateTeamEventTypeInput, @@ -83,16 +85,22 @@ export class OrganizationsEventTypesService { return this.teamsEventTypesService.getTeamEventTypeBySlug(teamId, eventTypeSlug, hostsLimit); } - async getTeamEventTypes(teamId: number): Promise { - return await this.teamsEventTypesService.getTeamEventTypes(teamId); + async getTeamEventTypes(teamId: number, sortCreatedAt?: SortOrderType): Promise { + return await this.teamsEventTypesService.getTeamEventTypes(teamId, sortCreatedAt); } async getOrganizationsTeamsEventTypes( orgId: number, skip = 0, - take = 250 + take = 250, + sortCreatedAt?: SortOrderType ): Promise { - return await this.organizationEventTypesRepository.getOrganizationTeamsEventTypes(orgId, skip, take); + return await this.organizationEventTypesRepository.getOrganizationTeamsEventTypes( + orgId, + skip, + take, + sortCreatedAt + ); } async updateOrganizationTeamEventType( diff --git a/apps/api/v2/src/modules/teams/event-types/controllers/teams-event-types.controller.ts b/apps/api/v2/src/modules/teams/event-types/controllers/teams-event-types.controller.ts index 029cfe50be..1beff0b685 100644 --- a/apps/api/v2/src/modules/teams/event-types/controllers/teams-event-types.controller.ts +++ b/apps/api/v2/src/modules/teams/event-types/controllers/teams-event-types.controller.ts @@ -136,12 +136,16 @@ export class TeamsEventTypesController { } @Get("/") - @ApiOperation({ summary: "Get a team event type" }) + @ApiOperation({ + summary: "Get team event types", + description: + 'Use the optional `sortCreatedAt` query parameter to order results by creation date (by ID). Accepts "asc" (oldest first) or "desc" (newest first). When not provided, no explicit ordering is applied.', + }) async getTeamEventTypes( @Param("teamId", ParseIntPipe) teamId: number, @Query() queryParams: GetTeamEventTypesQuery_2024_06_14 ): Promise { - const { eventSlug, hostsLimit } = queryParams; + const { eventSlug, hostsLimit, sortCreatedAt } = queryParams; if (eventSlug) { const eventType = await this.teamsEventTypesService.getTeamEventTypeBySlug( @@ -156,7 +160,7 @@ export class TeamsEventTypesController { }; } - const eventTypes = await this.teamsEventTypesService.getTeamEventTypes(teamId); + const eventTypes = await this.teamsEventTypesService.getTeamEventTypes(teamId, sortCreatedAt); return { status: SUCCESS_STATUS, diff --git a/apps/api/v2/src/modules/teams/event-types/services/teams-event-types.service.ts b/apps/api/v2/src/modules/teams/event-types/services/teams-event-types.service.ts index 79e28534ee..735cf9dd90 100644 --- a/apps/api/v2/src/modules/teams/event-types/services/teams-event-types.service.ts +++ b/apps/api/v2/src/modules/teams/event-types/services/teams-event-types.service.ts @@ -11,6 +11,8 @@ import { UsersService } from "@/modules/users/services/users.service"; import { UserWithProfile } from "@/modules/users/users.repository"; import { Injectable, NotFoundException, Logger } from "@nestjs/common"; +import type { SortOrderType } from "@calcom/platform-types"; + import { createEventType, updateEventType } from "@calcom/platform-libraries/event-types"; @Injectable() @@ -101,8 +103,8 @@ export class TeamsEventTypesService { return eventType; } - async getTeamEventTypes(teamId: number): Promise { - return await this.teamsEventTypesRepository.getTeamEventTypes(teamId); + async getTeamEventTypes(teamId: number, sortCreatedAt?: SortOrderType): Promise { + return await this.teamsEventTypesRepository.getTeamEventTypes(teamId, sortCreatedAt); } async updateTeamEventType( diff --git a/apps/api/v2/src/modules/teams/event-types/teams-event-types.repository.ts b/apps/api/v2/src/modules/teams/event-types/teams-event-types.repository.ts index 2d5c6d8306..01eef437b4 100644 --- a/apps/api/v2/src/modules/teams/event-types/teams-event-types.repository.ts +++ b/apps/api/v2/src/modules/teams/event-types/teams-event-types.repository.ts @@ -2,6 +2,8 @@ import { PrismaReadService } from "@/modules/prisma/prisma-read.service"; import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; import { Injectable } from "@nestjs/common"; +import type { SortOrderType } from "@calcom/platform-types"; + @Injectable() export class TeamsEventTypesRepository { constructor(private readonly dbRead: PrismaReadService, private readonly dbWrite: PrismaWriteService) {} @@ -79,11 +81,12 @@ export class TeamsEventTypesRepository { }); } - async getTeamEventTypes(teamId: number) { + async getTeamEventTypes(teamId: number, sortCreatedAt?: SortOrderType) { return this.dbRead.prisma.eventType.findMany({ where: { teamId, }, + ...(sortCreatedAt && { orderBy: { id: sortCreatedAt } }), include: { users: true, schedule: true, diff --git a/docs/api-reference/v2/openapi.json b/docs/api-reference/v2/openapi.json index 51c48d64b3..c9c9ab32f0 100644 --- a/docs/api-reference/v2/openapi.json +++ b/docs/api-reference/v2/openapi.json @@ -4470,6 +4470,7 @@ "get": { "operationId": "OrganizationsEventTypesController_getTeamEventTypes", "summary": "Get team event types", + "description": "Use the optional `sortCreatedAt` query parameter to order results by creation date (by ID). Accepts \"asc\" (oldest first) or \"desc\" (newest first). When not provided, no explicit ordering is applied.", "parameters": [ { "name": "Authorization", @@ -4523,6 +4524,16 @@ "schema": { "type": "number" } + }, + { + "name": "sortCreatedAt", + "required": false, + "in": "query", + "description": "Sort event types by creation date. When not provided, no explicit ordering is applied.", + "schema": { + "enum": ["asc", "desc"], + "type": "string" + } } ], "responses": { @@ -4816,6 +4827,7 @@ "get": { "operationId": "OrganizationsEventTypesController_getTeamsEventTypes", "summary": "Get all team event types", + "description": "Use the optional `sortCreatedAt` query parameter to order results by creation date (by ID). Accepts \"asc\" (oldest first) or \"desc\" (newest first). When not provided, no explicit ordering is applied.", "parameters": [ { "name": "Authorization", @@ -4876,6 +4888,16 @@ "default": 0, "type": "number" } + }, + { + "name": "sortCreatedAt", + "required": false, + "in": "query", + "description": "Sort event types by creation date. When not provided, no explicit ordering is applied.", + "schema": { + "enum": ["asc", "desc"], + "type": "string" + } } ], "responses": { @@ -11552,7 +11574,7 @@ "get": { "operationId": "EventTypesController_2024_06_14_getEventTypes", "summary": "Get all event types", - "description": "Hidden event types are returned only if authentication is provided and it belongs to the event type owner.\n \n Please make sure to pass in the cal-api-version header value as mentioned in the Headers section. Not passing the correct value will default to an older version of this endpoint.\n ", + "description": "Hidden event types are returned only if authentication is provided and it belongs to the event type owner.\n \n Use the optional `sortCreatedAt` query parameter to order results by creation date (by ID). Accepts \"asc\" (oldest first) or \"desc\" (newest first). When not provided, no explicit ordering is applied.\n \n Please make sure to pass in the cal-api-version header value as mentioned in the Headers section. Not passing the correct value will default to an older version of this endpoint.\n ", "parameters": [ { "name": "cal-api-version", @@ -11609,6 +11631,16 @@ "type": "number" } }, + { + "name": "sortCreatedAt", + "required": false, + "in": "query", + "description": "Sort event types by creation date. When not provided, no explicit ordering is applied.", + "schema": { + "enum": ["asc", "desc"], + "type": "string" + } + }, { "name": "Authorization", "in": "header", @@ -14420,6 +14452,7 @@ "get": { "operationId": "TeamsEventTypesController_getTeamEventTypes", "summary": "Get a team event type", + "description": "Use the optional `sortCreatedAt` query parameter to order results by creation date (by ID). Accepts \"asc\" (oldest first) or \"desc\" (newest first). When not provided, no explicit ordering is applied.", "parameters": [ { "name": "teamId", @@ -14446,6 +14479,16 @@ "schema": { "type": "number" } + }, + { + "name": "sortCreatedAt", + "required": false, + "in": "query", + "description": "Sort event types by creation date. When not provided, no explicit ordering is applied.", + "schema": { + "enum": ["asc", "desc"], + "type": "string" + } } ], "responses": { @@ -27467,6 +27510,14 @@ "type": "string", "nullable": true }, + "avatarUrl": { + "type": "string", + "nullable": true + }, + "bio": { + "type": "string", + "nullable": true + }, "timeFormat": { "type": "number" }, @@ -27493,6 +27544,8 @@ "username", "email", "name", + "avatarUrl", + "bio", "timeFormat", "defaultScheduleId", "weekStart", diff --git a/packages/platform/types/event-types/event-types_2024_06_14/inputs/get-event-types-query.input.ts b/packages/platform/types/event-types/event-types_2024_06_14/inputs/get-event-types-query.input.ts index dbf0d8d1a3..0641297687 100644 --- a/packages/platform/types/event-types/event-types_2024_06_14/inputs/get-event-types-query.input.ts +++ b/packages/platform/types/event-types/event-types_2024_06_14/inputs/get-event-types-query.input.ts @@ -1,6 +1,8 @@ import { ApiPropertyOptional } from "@nestjs/swagger"; import { Transform } from "class-transformer"; -import { IsNumber, IsOptional, IsString } from "class-validator"; +import { IsEnum, IsNumber, IsOptional, IsString } from "class-validator"; + +import { SkipTakePagination, SortOrder, SortOrderType } from "../../../pagination/pagination.input"; export class GetEventTypesQuery_2024_06_14 { @IsOptional() @@ -46,6 +48,14 @@ export class GetEventTypesQuery_2024_06_14 { type: Number, }) orgId?: number; + + @ApiPropertyOptional({ + enum: SortOrder, + description: "Sort event types by creation date. When not provided, no explicit ordering is applied.", + }) + @IsOptional() + @IsEnum(SortOrder) + sortCreatedAt?: SortOrderType; } export class GetTeamEventTypesQuery_2024_06_14 { @@ -64,6 +74,24 @@ export class GetTeamEventTypesQuery_2024_06_14 { "Specifies the maximum number of hosts to include in the response. This limit helps optimize performance. If not provided, all Hosts will be fetched.", }) hostsLimit?: number; + + @ApiPropertyOptional({ + enum: SortOrder, + description: "Sort event types by creation date. When not provided, no explicit ordering is applied.", + }) + @IsOptional() + @IsEnum(SortOrder) + sortCreatedAt?: SortOrderType; +} + +export class GetOrganizationEventTypesQuery_2024_06_14 extends SkipTakePagination { + @ApiPropertyOptional({ + enum: SortOrder, + description: "Sort event types by creation date. When not provided, no explicit ordering is applied.", + }) + @IsOptional() + @IsEnum(SortOrder) + sortCreatedAt?: SortOrderType; } function TransformUsernames() { diff --git a/packages/platform/types/pagination/pagination.input.ts b/packages/platform/types/pagination/pagination.input.ts index be2853e64d..9e5d403b52 100644 --- a/packages/platform/types/pagination/pagination.input.ts +++ b/packages/platform/types/pagination/pagination.input.ts @@ -2,6 +2,13 @@ import { ApiPropertyOptional } from "@nestjs/swagger"; import { Transform } from "class-transformer"; import { IsNumber, Min, Max, IsOptional } from "class-validator"; +export enum SortOrder { + ASC = "asc", + DESC = "desc", +} + +export type SortOrderType = `${SortOrder}`; + export class Pagination { @ApiPropertyOptional({ description: "The number of items to return", example: 10 }) @Transform(({ value }: { value: string }) => value && parseInt(value))